Bash 管道中的节点如何查看但不使用其输入流?

Bash 管道中的节点如何查看但不使用其输入流?

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
$

答案4

虽然不是标准的 Unix 实用程序或 Bash 脚本,但我决定使用以下方法解决这个特定示例中的问题ifne更多实用程序

printf "%s\n" a b print c | grep print | ifne echo found

输出:

found
printf "%s\n" a b c | grep print | ifne echo found

输出:


@尼克·沃斯lfne他的文章中提到回答如何检查管道是否为空,如果不是则对数据运行命令?

谢谢至@mosvy为了指称我来回答这个现有的问题。

相关内容