有没有办法将一个函数的输出通过管道传输到另一个函数,但前提是是输出?
答案1
以下ifnotempty
函数将其输入通过管道传输到作为参数传递的命令,但如果输入为空,则不执行任何操作。通过写入使用它source --foo
来通过管道传输。sink --bar
source --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
不读取超过它在标准输入上被要求读取的一个字节。 - 我认为它将是Linux
head -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
答案4
至少这样的方法是可行的:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
请注意,以上内容将把换行符和其他特殊字符视为输出,因此传递给该 if 语句的空行将被视为输出。如果您的输出通常应高于 1 个字节,则只需提高 -gt 限制 :)