避免由于缺少命令而导致多个管道损坏

避免由于缺少命令而导致多个管道损坏

在 shell 脚本中,我经常使用多个管道,如下所示:

cmd1 | cmd2 | cmd3

现在,如果cmd2缺少管道将导致“损坏”并且cmd3不会接收任何输入。

作为解决方法,我可以显式测试 cmd2 是否存在,但这需要一些我想避免的代码复制。

相反,我想要一个更简洁的测试,如下所示:

cmd1 | cmd2; [ $? -eq 127 ] && cat | cmd3

答案1

您可以编写一个迷你函数以使其更加简洁:

ifexists(){
    if command -v "$1"
    then "$@"
    else echo "doing cat for missing $1" >&2
         cat
    fi
}

echo hi | ifexists mycommand | cat -n

答案2

根据您的示例,您似乎正在寻找一种将优先级低于|, (即&&||)的操作的参数分组的方法。

{和元}字符可用于以这种方式进行分组。

上面的示例可以这样写(使用 的退出状态来which确定是否cmd2存在)。

cmd1 | { which cmd2 >/dev/null && cmd2 || cat; } | cmd3

例如

printf "hi\n" | { : && rev || cat; } | cat

会打印ih

您使用子外壳的建议也将起作用,但不必要地使用另一个进程

printf "hi\n" | ( : && rev || cat ) | cat

我想说,如果您if在管道外部使用显式的,那么它可能不那么棘手,并且可维护性更好。

if [ which cmd2 >/dev/null ]
then
    cmd1 | cmd3
else
    cmd1 | cmd2 | cmd3
fi

相关内容