【发布时间】:2022-05-08 02:53:01
【问题描述】:
注意:问题不重复Ignoring specific errors in a shell script。
假设需要捕获文件编码表示的前导字符。
在 shell 中(在 Bash 中测试),很容易使用以下形式:
encoded="$(< file base64 | head -c16)"
需要的语句功能,除非对环境进行某些更改。
考虑以下几点:
set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$(< file base64 | head -c16)"
最后一行将导致脚本终止,因为base64 给出的非零返回状态 (141),对关闭的管道不满意。返回状态传播到管道,然后传播到调用外壳。
不良影响需要解决方法,如下所示:
set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$((< file base64 || :) | head -c16)"
: 与关键字 true 具有相同的效果,以评估为非错误。
但是,这种方法会导致进一步的不良影响。
以下显示了具有不同错误的变体:
set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$((< /not/a/real/file base64 || :) | head -c16)"
echo $?
打印的代码为零。现在,一个真正的错误已被掩盖。
最明显的解决方案如下,相当冗长
set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$((< /not/a/real/file base64 || [ $? == 141 ]) | head -c16)"
echo $?
有更紧凑的表格吗?是否有任何可用的环境更改,使得语句只掩盖特定的状态代码,而没有显式的内联表达式?
【问题讨论】:
-
我怀疑还有什么更好的。区分不同的退出代码比较少见,因此没有捷径可走。
-
您的解决方案似乎不错;如果你经常使用不守规矩的命令,那么你可以定义一个函数
mybase64() { base64 "$@" || [[ $? == 141 ]]; } -
我认为你不需要圆括号,这会导致进程分叉。花括号应该足够了。
-
@ceving:您能否为这个想法推荐一个可行的例子?我还没有发现。
-
您需要重定向作为输入吗?对于@ceing 的含义,我猜是:
encoded="$( { base64 $1 ; } | head -c16)"以$1作为文件。