使管道以非空返回为条件

Tgr*_*Tgr 21 bash pipe

有没有办法将一个函数的输出通过管道传输到另一个函数,但前提有输出?

Ran*_*tka 22

这应该适合你

$ --a function-- | [ xargs -r ] --another function--
Run Code Online (Sandbox Code Playgroud)

一个例子

$ echo -e "\n\n" | xargs -r ls
$ # No output. ls did not run.
$ echo -e "\n\n1" | xargs -r ls
ls: cannot access 1: No such file or directory
Run Code Online (Sandbox Code Playgroud)

这很简单,但它应该适合你。如果您的“函数”在管道中发送一个空字符串甚至换行符,xargs -r 将阻止通过“另一个函数”。

xargs 参考:http : //www.oreillynet.com/linux/cmd/cmd.csp? path = x/xargs

-r, --no-run-if-empty
Do not run command if standard input contains only blanks.
Run Code Online (Sandbox Code Playgroud)

  • xargs 不充当管道 (3认同)

Gil*_*il' 12

以下ifnotempty函数将其输入通过管道传递给作为参数传递的命令,但如果输入为空则不执行任何操作。使用它通过写入管道source --foo进入。sink --barsource --foo | pipe_if_not_empty sink --bar

pipe_if_not_empty () {
  head=$(dd bs=1 count=1 2>/dev/null; echo a)
  head=${head%a}
  if [ "x$head" != x"" ]; then
    { printf %s "$head"; cat; } | "$@"
  fi
}
Run Code Online (Sandbox Code Playgroud)

设计注意事项:

  • 我希望这个实现可以在所有 POSIX/Unix 平台上工作,尽管严格来说它不符合标准:它依赖于dd读取的字节数不超过它被告知在其标准输入上读取的一个字节。
  • 我认为head -c 1这将是dd bs=1 count=1 2>/dev/nullLinux 上的合适替代品。
  • 另一方面,head -n 1它不合适,因为head通常会缓冲其输入,并且可能读取的内容多于它输出的一行——而且由于它是从管道中读取的,因此额外的字节会丢失。
  • read -r head甚至read -r -n 1 head不适合这里,因为如果第一个字符是换行符,head则会设置为空字符串,从而无法区分空输入和以空行开头的输入。
  • 我们不能只写,head=$(head -c 1)因为如果第一个字符是换行符,命令替换会去除最后的换行符,从而无法区分空输入和以空行开头的输入。
  • 在bash和ksh或zsh的,可以取代cat通过</dev/stdin对微观性能增益。

如果您不介意将整个中间数据存储在内存中,这里有一个非常简单的pipe_if_not_empty.

pipe_if_not_empty () {
  input=$(cat; echo a);
  if [ "x$input" != x"a" ]; then
    { printf %s "${input%a}"; } | "$@"
  fi
}
Run Code Online (Sandbox Code Playgroud)

这是一个稍微简单的实现,但有以下注意事项:

  • 当且仅当源产生的数据仅由换行符组成时,它才被认为是空的。(这实际上可能是可取的。)
  • 送入接收器的数据以一个换行符结束,无论源生成的数据以多少换行符结束。(这可能是一个问题。)

同样,整个数据都存储在内存中。

pipe_if_not_empty () {
  input=$(cat);
  if [ "x$input" != x"" ]; then
    { printf '%s\n' "${input}"; } | "$@"
  fi
}
Run Code Online (Sandbox Code Playgroud)


小智 12

ifne(1)moreutils正是如此。Moreutils 至少在 Debian 和 Ubuntu 中可以作为一个包使用,可能在其他发行版中也是如此。


小智 5

下面的函数尝试读取第一个字节,如果成功则回显该字节并捕获其余字节。应该高效且 100% 可移植。

if_read() {
    IFS="" read -rN 1 BYTE && { echo -nE "$BYTE"; cat; } | "$@";
}
Run Code Online (Sandbox Code Playgroud)

测试用例:

$ echo -n | if_read wc -c
$ echo | if_read wc -c
1
$ echo -en "\nX" | if_read wc -c
2
$
Run Code Online (Sandbox Code Playgroud)