我有一些代码,我想要$?变量。
VARIABLE=`grep "searched_string" test.log | sed 's/searched/found/'`
有没有办法测试整条线(而不仅仅是sed命令)是否成功完成?如果我在它之后尝试以下代码:
if [ "$?" -ne 0 ]
then
echo 1
exit
fi
即使语句的grep部分失败,它也不会运行。
有人可以说明如何解决此问题吗?
答案 0 :(得分:7)
使用
echo ${PIPESTATUS[@]}
将打印出所有命令的退出状态数组。
$ ls | grep . | wc -l
28
$ echo ${PIPESTATUS[@]}
0 0 0
但
$ ls | grep nonexistentfilename | wc -l
0
$ echo ${PIPESTATUS[@]}
0 1 0 #the grep returns 1 - pattern not found
或
$ ls nonexistentfilename | grep somegibberish | wc -l
ls: nonexistentfilename: No such file or directory
0
$ echo ${PIPESTATUS[@]}
1 1 0 #ls and grep fails
确切的命令状态
echo ${PIPESTATUS[1]} #for the grep
这里也是
set -o pipefail
来自文档
<强> pipefail 强>
如果设置,管道的返回值是的值 last(最右边)命令以非零状态退出,如果是,则返回零 管道中的所有命令都成功退出。这个选项是 默认情况下已禁用。
$ ls nonexistentfile | wc -c
ls: nonexistentfile: No such file or directory
0
$ echo $?
0
$ set -o pipefail
$ ls nonexistentfile | wc -c
ls: nonexistentfile: No such file or directory
0
$ echo $?
1
你可能尝试了下一个:
VARIABLE=$(grep "searched_string" test.log | sed 's/searched/found/')
echo "${PIPESTATUS[@]}"
当然,这不起作用,因为整个$(...)
部分在子shell(另一个进程)中运行,因此当子shell退出时,所创建的任何变量都会丢失。 (在)
)
您应该将整个PIPESTATUS机制放入$(...)
,如下一个:
variable=$(
grep "searched_string" test.log | sed 's/searched/found/'
# do something with PIPESTATUS
# you should not echo anythig to stdout (because will be captured into $variable)
# you can echo on stderr - e.g.
echo "=${PIPESTATUS[@]}=" >&2
)
此外,评论的第二行是一个解决方案,例如:
var_with_status=$(command | commmand2 ; echo ":DELIMITER:${PIPESTATUS[@]}")
现在,$var_with_status
不仅包含command | command2
的结果,还包含PIPESTATUS的结果,用一些唯一的分隔符分隔,因此您可以提取它......
此外,set -o pipefail
会显示结果 - 如果您不需要确切的失败位置。
你也可以在一些临时文件(在子shell中)编写PIPESTATUS,父母可以读取它并删除临时文件......
也可以将PIPESTATUS打印到子shell中的不同文件描述符中,并在父shell中读取此描述符,但是....
...注意不要落入XY problem,你将制作极其复杂的剧本,只是因为你不想改变处理的逻辑。
e.g。你总是可以将脚本分成安全的部分,例如:
var1=$(grep 'str' test.log)
#check the `$var1` and do something with the error indicated with `$?`
var2=(sed '....' <<<"$var1")
#check the `$var2` and do something with the error indicated with `$?`
#and so on
够简单吗?
所以,问问自己 - 你真的需要如何让PIPESTATUS形成一个子壳吗?
Ps:不要使用大写变量名。可能会干扰某些环境变量并导致难以调试的问题。