I have a program that output some text and then a continuous stream of characters:
JavaScript
x
perl -E '$|=1;print "OUTn";print "A" and sleep 1 for 1..10'
I want to exit this program as soon as “A” is seen in the output and I tried:
JavaScript
grep -m 1 A <(perl -E '$|=1;print "OUTn";print "A" and sleep 1 for 1..10')
However, it seems like grep doesn’t see the “A”s until the perl program exits.
I also tried with sed with no luck;
JavaScript
sed /A/q <(perl -E '$|=1;print "OUTn";print "A" and sleep 1 for 1..10')
Any ideas how I can solve this?
Advertisement
Answer
The issue here is that both grep
and sed
process their input linewise unless they are told otherwise. One workaround is to insert newlines, e.g. with coreutils fold
:
JavaScript
grep -m 1 A
<(perl -E '$|=1;print "OUTn";print "A" and sleep 1 for 1..10' | fold -w1)
But this still has issues because of pipe-buffering. You can disable this with coreutils stdbuf
:
JavaScript
grep -m 1 A
<(perl -E '$|=1;print "OUTn";print "A" and sleep 1 for 1..10' |
stdbuf -o0 fold -w1)
Another alternative is to use dd
, e.g.:
JavaScript
perl -E '$|=1;print "OUTn";print "A" and sleep 1 for 1..10' |
while :; do
c=$(dd bs=1 count=1 status=none)
if [[ "$c" == "A" ]]; then
break
else
: Do something else
fi
done