使管道以非空返回为条件

使管道以非空返回为条件

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

答案1

以下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
}

设计说明:

  • 我希望这个实现能够在所有 POSIX/Unix 平台上工作,尽管严格来说它不符合标准:它依赖于dd不读取超过它在标准输入上被要求读取的一个字节。
  • 我认为它将是Linuxhead -c 1的合适替代品。dd bs=1 count=1 2>/dev/null
  • 另一方面,这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
}

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

  • 当且仅当源生成的数据仅由换行符组成时,才将其视为空。 (事实上这可能是可取的。)
  • 无论源生成的数据以多少个换行符结尾,输入到接收器的数据都恰好以一个换行符结尾。(这可能是一个问题。)

再次,整个数据都存储在内存中。

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

答案2

这应该对你有用

$ --a function-- | [ xargs -r ] --another function--

一个例子

$ 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

它很简单,但应该对你有用。如果你的“a 函数”向管道发送一个空字符串甚至一个换行符,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.

答案3

如果是的话(1)更多工具确实如此。Moreutils 至少在 Debian 和 Ubuntu 中以软件包形式提供,在其他发行版中可能也可用。

答案4

至少这样的方法是可行的:

yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi

请注意,以上内容将把换行符和其他特殊字符视为输出,因此传递给该 if 语句的空行将被视为输出。如果您的输出通常应高于 1 个字节,则只需提高 -gt 限制 :)

相关内容