Bash 管道中的节点如何只查看而不使用其输入流?
例如,我如何修改以下脚本,使其输出“print”而不是什么也不输出?特别是,我如何修改或替换,grep --quiet print
以便它只查看但不消耗其输入?
printf "%s\n" a b print c |
if grep --quiet print
then
grep print | cat
fi
输出:
期望的输出:
print
peek
理想情况下,我寻找一个类似于 的程序grep
,但不消耗其输入。 peek print
如果在输入中找到“print”,则返回错误代码 0;如果没有,则返回非零错误代码。
以下是peek
我的示例中的工作方式:
printf "%s\n" a b print c |
if peek print
then
grep print | cat
fi
输出:
print
我想这样做而不是简单地过滤结果的原因grep print
是避免处理可能导致错误的空搜索结果。
答案1
我能想到的一个直接方法是使用临时存储来输出。只需对代码进行最少的修改即可完成,如下所示:
atmp=$(mktemp "/tmp/XXXXXX")
printf "%s\n" a b print c | tee $atmp |
if grep --quiet print
then
grep print $atmp
fi
rm $atmp #cleanup
对于小批量的输出来说,这可能是可以接受的。
答案2
另一种类似于@Tagwint 的方法回答是将结果存储grep print
在 shell 变量中,然后仅在有搜索结果时才打印该变量的内容:
printf "%s\n" a print b print c |
if result=$(grep print)
then
echo "$result";
fi
输出:
print
print
当搜索结果不太大时,这是可以接受的。
答案3
fionread
我还使用以下方法解决了这个具体示例中的问题@mosvy实施在他的回答到如何检查管道是否为空,如果不是则对数据运行命令?。
printf "%s\n" a b print c | grep print | ./fionread echo found
输出:
found
printf "%s\n" a b c | grep print | ./fionread echo found
输出:
请注意,可以在 FreeBSD 11.3 上gcc
轻松编译:fionread.c
$ gcc -o fionread fionread.c
$ echo test | grep test | ./fionread echo found
found
$ echo | grep test | ./fionread echo found
$