运行此代码时:
while true; do printf "Match Unmatch\n"; sleep 1s; done | grep -o "Match"
在终端中,grep
找到单词Match
.我得到输出:
Match
Match
Match
...
但是,当我运行以下代码时:
while true; do printf "Match Unmatch"; sleep 1s; done | grep -o "Match"
然后grep
似乎什么也没发现,至少它什么也没打印。 grep 是否在等待永远不会出现的换行符?有没有某种方法可以使 grep、sed 或类似工具在流中捕获匹配而无需换行符?
答案1
Grep 主要查找包含给定模式匹配项的行。根据模式的不同,可能无法在不查看整行的情况下确定一行是否匹配。对于grep Match
,这是可能的,但是对于grep 'Match$'
,则不可能。使用 时grep -o Match
,grep 可以Match
一看到就打印,但是使用 时grep -E -o '(Match)+'
,如果 grep 读到了MatchMa
,它不知道是否tch
会跟随。
Grep 不实现在看到整行之前可以写入一些输出的特殊情况。 (我认为它没有实现任何这种特殊情况,但我不完全确定:GNU grep 有多种模式,具体取决于行为略有不同的模式。)它在尝试匹配之前只读取一整行。
如果有一个字符从未出现在匹配文本中并且总是(或至少经常)出现在匹配之间,则将该字符转换为换行符。 (或者进入空字节并使用grep -z
。)
while true; do printf "Match Unmatch"; sleep 1s; done | stdbuf -o0 tr ' ' '\n' | grep -o "Match"
请注意使用 来stdbuf -o0
防止tr
缓冲其输出。如果您通过管道传输 grep 的输出,那么 grep 也需要它,或者使用grep --line-buffered
. (--line-buffered
缓冲输出grep 的;它对 grep 读取输入的方式没有影响,并且当 grep 打印到终端时它默认处于打开状态。)