开发者

diff on two program with same input?

开发者 https://www.devze.com 2023-04-09 17:01 出处:网络
#!bin/sh i=0; while read inputline do array[$i]=$inputline; i=`expr $i + 1` done j=i; ./a.out > test/temp;
#!bin/sh

i=0;
while read inputline
do
        array[$i]=$inputline;
        i=`expr $i + 1`
done

j=i;

./a.out > test/temp;
while [$i -gt 0]
do
echo ${array[$i]}
i=`expr $i -  1`;
done

./test > test/temp1;
while [$j -gt 0]
do
echo ${array[$j]}
j=`expr $j -  1`;
done

diff test/temp1 test/temp

What's wrong with the above code? Essentially what it's meant to do is take some开发者_StackOverflow社区 input from stdin and then provide the same input to two separate programs and then put their output into another file and then diff them. How come it doesn't work?


I see a few things that could be problems.

First, usually the path to sh is /bin/sh. I would expect the shebang line to be something like this:

#!/bin/sh

This may not be causing an error, however, if you're calling sh on the command line.

Second, the output from your while loops needs to be redirected to your executables:

{
    while [ $i -lt $lines ]
    do
        echo ${array[$i]}
        i=`expr $i +  1`;
    done
} | ./a.out > test/temp;

Note: I tested this on Mac OS X and Linux, and sh is aliased to bash on both operating systems. I'm not entirely sure that this construct works in plain old sh.

Third, the indexing is off in your while loops: it should go from 0 to $i - 1 (or from $i - 1 to 0). As written in your example, it goes from $i to 1.

Finally, "test" is used as both your executable name and the output directory name. Here's what I ended up with:

#!/bin/sh

lines=0;
while read inputline
do
        array[$lines]=$inputline;
        lines=`expr $lines + 1`
done

i=0
{
    while [ $i -lt $lines ]
    do
        echo ${array[$i]}
        i=`expr $i +  1`;
    done
} | ./a.out > test/temp;

i=0
{
    while [ $i -lt $lines ]
    do
        echo ${array[$i]}
        i=`expr $i +  1`;
    done
} | ./b.out > test/temp1;

diff test/temp1 test/temp

Another way to do what you want would be to store your test input in a file and just use piping to feed the input to the programs. For example, if your input is stored in input.txt then you can do this:

cat input.txt | a.out > test/temp
cat input.txt | b.out > test/temp1
diff test/temp test/temp1


Another approach is to capture stdin like this:

#!/bin/sh
input=$(cat -)
printf "%s" "$input" | ./a.out > test/temp
printf "%s" "$input" | ./test  > test/temp1
diff test/temp test/temp1

or, using bash process substitution and here-strings:

#!/bin/bash
input=$(cat -)
diff <(./a.out <<< "$input") <(./test <<< "$input")


What's wrong?

The semi-colons are not necessary, though they do no harm.

The initial input loop looks OK.

The assignment j=i is quite different from j=$i.

You run the program ./a.out without supplying it any input.

You then have a loop that was meant to echo the input. It provides the input backwards compared with the way it was read.

You repeat the program execution of ./test without supplying any input, followed by a repeat loop that was meant to echo the input, but this one fails because of the misassignment.

You then run diff on the two outputs produced from uncertain inputs.

You do not clean up the temporary files.

How to do it

This script is simple - except that it ensures that temporary files are cleaned up.

tmp=${TMPDIR:-/tmp}/tester.$$
trap "rm -f $tmp.?; exit 1" 0 1 2 3 13 15

cat - > $tmp.1
./a.out < $tmp.1 > $tmp.2
./test  < $tmp.1 > $tmp.3
diff $tmp.2 $tmp.3

rm -f $tmp.?
trap 0
exit 0

The first step is to capture the input in a file $tmp.1. Then run the two test programs, capturing the output in files $tmp.2 and $tmp.3. Then take the difference of the two files.

The first trap line ensures that the temporary files are removed when the shell exits, or if it receives a signal from the set { HUP, INT, QUIT, PIPE, TERM }. The second trap line cancels the 'exit' trap, so that the script can exit successfully. (You can relay the exit status of diff to the calling program (shell) by capturing its exit status status=$? and then using exit $status.)


If all you want to do is supply the same stdin to two programs you might like to use process substitution together with tee. Assuming you can cat your input from a file (or just using the tee part, if you want it interactive-ish) you could use something like this:

cat input | tee >(./p1 > p1.out) >(./p2 > p2.out) && diff p1.out p2.out
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号