Skip to content
Advertisement

How do I grep or sed in a continuous stream of characters?

I have a program that output some text and then a continuous stream of characters:

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:

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;

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:

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:

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.:

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
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement