Insane redirection behavior

Hi guys,

I know computers don't misbehave.
But I'm puzzled by what's happening right know in a script :

I simplified the example to point out what seems weird to me.
Don't try to find any sense to this stupid script.

There are 10 rows in /tmp/tmp.txt

i=0
tmpfile=/tmp/tmp.txt
while read -r; do
    echo "$REPLY" > /dev/null
    sed "1,$((++i))d" $tmpfile | wc -l
done < $tmpfile
i=0
tmpfile=/tmp/tmp.txt
while read -r; do
    echo "$REPLY" > /dev/null
    sed "1,$((++i))d" $tmpfile > /tmp/output; wc -l /tmp/output
done < $tmpfile

In the first script, I count line from the output of sed. In the second one, I first output sed to a file and then count the lines of that file.
I see no reason why the output would be different... YET:

root@debian:~# ./script1
9
9
9
9
9
9
9
9
9
9
root@debian:~# ./script2
9 /tmp/output
8 /tmp/output
7 /tmp/output
6 /tmp/output
5 /tmp/output
4 /tmp/output
3 /tmp/output
2 /tmp/output
1 /tmp/output
0 /tmp/output

This is driving me crazy.
Do you have any sane explanation?!?

Regards
Santiago

It should be easier if you also post the input file and the desired output.

The first script is running sed in a subshell environment; the second is not. The subshell is a byproduct of the shell's pipeline implementation. The difference is that when $i is incremented in a subshell, the new value is not available in the parent shell.

One workaround would be to increment the variable prior to calling sed.

Regards,
Alister

2 Likes

The input file is random. It just contains 10 rows but we don't care what they are.
The output should be counting down from 9 to 0.

---------- Post updated at 16:40 ---------- Previous update was at 16:23 ----------

Hi alister,

You were right.
Here are the two new scripts...

i=0
tmpfile=/tmp/tmp.txt
while read -r; do
    echo "$REPLY" > /dev/null
    ((++i))
   sed "1,${i}d" $tmpfile | wc -l
done < $tmpfile
i=0
tmpfile=/tmp/tmp.txt
while read -r; do
    echo "$REPLY" > /dev/null
    ((++i))
    sed "1,${i}d" $tmpfile > /tmp/output; wc -l /tmp/output
done < $tmpfile

... and their output...

root@debian:~# ./script1
9
8
7
6
5
4
3
2
1
0
root@debian:~# ./script2
9 /tmp/output
8 /tmp/output
7 /tmp/output
6 /tmp/output
5 /tmp/output
4 /tmp/output
3 /tmp/output
2 /tmp/output
1 /tmp/output
0 /tmp/output

Regards
Santiago