I have happened upon a command that sometimes works and sometimes does not, even when executed multiple times in rapid succession in a bash
shell (I have not tested the behavior in other shells). The problem has been localized to the reading of a variable in the BEGIN
block of an awk
statement at the end of the pipe line. During some executions, the variable is correctly read in the BEGIN
block and during other executions, the operation fails. Supposing this aberrant behavior can be reproduced by others (and is not a consequence of some problem with my system), can its inconsistency be explained?
Take as input the following file called tmp
:
cat > tmp <<EOF
a a
b *
aa a
aaa a
aa a
a a
c *
aaa a
aaaa a
d *
aaa a
a a
aaaaa a
e *
aaaa a
aaa a
f *
aa a
a a
g *
EOF
On my system, the pipe line
awk '{if($2!~/\*/) print $1}' tmp | tee >(wc -l | awk '{print $1}' > n.txt) | sort | uniq -c | sort -k 1,1nr | awk 'BEGIN{getline n < "n.txt"}{print $1 "\t" $1/n*100 "\t" $2}'
will either produce the correct output:
4 28.5714 a
4 28.5714 aaa
3 21.4286 aa
2 14.2857 aaaa
1 7.14286 aaaaa
or the error message:
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
How can a command possibly give different output when run twice in succession when no random number generation is involved and no change to the environment is made in the interim?
To demonstrate how absurd the behavior is, consider the output generated by executing the above pipe line ten times consecutively in a loop:
for x in {1..10}; do echo "Iteration ${x}"; awk '{if($2!~/\*/) print $1}' tmp | tee >(wc -l | awk '{print $1}' > n.txt) | sort | uniq -c | sort -k 1,1nr | awk 'BEGIN{getline n < "n.txt"}{print $1 "\t" $1/n*100 "\t" $2}'; done
Iteration 1
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
Iteration 2
4 28.5714 a
4 28.5714 aaa
3 21.4286 aa
2 14.2857 aaaa
1 7.14286 aaaaa
Iteration 3
4 28.5714 a
4 28.5714 aaa
3 21.4286 aa
2 14.2857 aaaa
1 7.14286 aaaaa
Iteration 4
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
Iteration 5
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
Iteration 6
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
Iteration 7
4 28.5714 a
4 28.5714 aaa
3 21.4286 aa
2 14.2857 aaaa
1 7.14286 aaaaa
Iteration 8
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
Iteration 9
4 28.5714 a
4 28.5714 aaa
3 21.4286 aa
2 14.2857 aaaa
1 7.14286 aaaaa
Iteration 10
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
Note: I have also tried closing the file (awk close
) after reading the variable, in case the problem relates to the file being left open. However, the inconsistent output remains.
$1/n*100
, specifically byn
. If for example, you remove thatn
your script runs fine. This should be related ton
value read fromn.txt
.28.5714 a
occurs 4 times? I think you'd have a lot more luck withuniq
orgrep -c
. My bad - I see that pipeline is a lot longer than I at first realized - and I mostly have the same question that ^ previous guy did - n? It some kind of formulae related to percentage like 4 times is close to 27% - but there's something else. 2% else. Anyway, I'm sure it can be much simplified and I urge you to try.sort
- for instance - is never a back-pipe friendly process.