我需要在设置了set -e
的脚本中执行命令。此命令是通用脚本流的一个例外,因为它可能会失败并且不会很关键:脚本可以继续。我希望该命令能够不中断脚本;相反,我想保留退出代码供以后评估。
我提出了以下脚本:
#!/bin/bash
set -e
false && res1=$? || res1=$?
true && res2=$? || res2=$?
echo $res1
echo $res2
(我的命令将取代false
或true
)
这是正确的方法吗?
顺便说一句,这个非常相似的结构根本不起作用:
#!/bin/bash
set -e
false || res1=$? && res1=$?
true || res2=$? && res2=$?
echo $res1
echo $res2
测试其中一条建议:
#!/bin/bash
set -e
false || { res1=$?; true; }
true || { res2=$?; true; }
echo $res1
echo $res2
这不起作用。结果是:
1
(empty line)
答案 0 :(得分:6)
请勿尝试使用&&
和||
来形成三元表达式;它太脆弱了。只需使用if
声明。
if cmd; then res=$?; else res=$?; fi
更好(?)但是,您可以将赋值置于条件本身,减少重复,但代价是看似空洞的if
语句:
if cmd; res=$?; then :; fi
虽然可以用一个||
写得更清楚:
{ cmd; res=$?; } || true
(注意我已经可以互换使用true
和:
; POSIX保证:
是内置的shell,但true
可能更具可读性。 )
答案 1 :(得分:1)
在&&
之后放置||
没有您想要的效果。例如,
false || echo true && echo false
将打印true和false,即无论第一个命令是否成功,都将执行&&
之后的任何内容。你可以这样做:
command && res1=$? || res1=$?
在这种情况下,如果command
成功,第三个不会被执行,如果失败,第二个不会被执行。
修改
提到chepnar时,&&
和||
的使用并非完全证明。这种行为无法保证。
答案 2 :(得分:0)
不是两次捕获相同的退出代码,为什么不关闭-e
,捕获退出状态并再次启用-e
,如下所示:
#!/bin/bash
set -e
set +e # turn off exit on error
false; res1=$? # run command1 and capture exit status1
true; res2=$? # run command2 and capture exit status2
set -e # turn on exit on error
echo $res1
echo $res2