如何在连续的字符流中进行 grep 或 sed?

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

我有一个程序可以输出一些文本,然后是连续的字符流:

perl -E '$|=1;print "OUT\n";print "A" and sleep 1 for 1..10'

我想在输出中看到“A”后立即退出此程序,我试过:

grep -m 1 A <(perl -E '$|=1;print "OUT\n";print "A" and sleep 1 for 1..10')

但是,似乎 grep 在 perl 程序退出之前看不到“A”。

我也尝试过使用 sed 但没有成功;

sed /A/q <(perl -E '$|=1;print "OUT\n";print "A" and sleep 1 for 1..10')

有什么办法可以解决这个问题吗?

这里的问题是 grepsed 都按行处理它们的输入,除非另有说明。一种解决方法是插入换行符,例如使用 coreutils fold:

grep -m 1 A \
  <(perl -E '$|=1;print "OUT\n";print "A" and sleep 1 for 1..10' | fold -w1)

但是由于管道缓冲,这仍然存在问题。您可以使用 coreutils stdbuf:

禁用它
grep -m 1 A \
  <(perl -E '$|=1;print "OUT\n";print "A" and sleep 1 for 1..10' |
    stdbuf -o0 fold -w1)

另一种选择是使用 dd,例如:

perl -E '$|=1;print "OUT\n";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