2016-09-19 66 views
1

我有一个shell脚本,用于检查窗口行尾。Bash“set -e”和否定返回码

set -e 

(! git ls-files | xargs grep -I $'\r') 

我正在使用“!”字符来否定命令的返回码。当找到带回车的文件时,Grep将返回代码0,并且“!”否定返回码的值为1,脚本退出。当使用grep(没有xargs)时,这个工作方式没有括号。当使用xargs时,根据$?发生否定,因为“echo $?”将打印“1”,但脚本不会退出!在整个命令周围添加括号后,它按预期工作。为什么需要括号?

+0

“*与grep(没有xargs)一起使用时,这个工作方式没有括号。*”这有点不清楚。你会显示代码吗? – Leon

+0

_“脚本不退出”_也不清楚。 –

+2

['set -e'充满了陷阱](http://mywiki.wooledge.org/BashFAQ/105),以至于bash社区对它是否是一个好主意非常分歧。 –

回答

3

您的问题与xargs无关。

bash的-e选项有点棘手。

-e退出立即如果管道(其可以由单个 简单命令的),一个列表,或化合物命令 ,退出与非零 状态。 壳如果 失败的指令是下面的一个whileuntil关键字命令列表的一部分立即 ,测试 以下的ifelif保留字的一部分不退出,任何 命令的一部分在一个&&执行或||名单,除了在最终&&||,在 管道的任何命令,但最后还是命令 如果命令的返回值 正在反转!

让我们来看一个非常简单的例子:

$ cat exit_on_error_test.sh 
#!/bin/bash 

trap 'echo Interrupted because of an error' ERR 
set -e 

! true 
echo Exit status: $? 

$ ./exit_on_error_test.sh 
Exit status: 1 
$ 

因此,即使的“! true”是非零,剧本被允许运行至年底,并输出值退出状态的退出状态。这是因为我们没有任何失败的命令 - 非零退出代码是由于故意的否定。但是,如果我们在括号中附上“! true”,我们将引入失败的(复合)命令。

$ cat exit_on_error_test.sh 
#!/bin/bash 

trap 'echo Interrupted because of an error' ERR 
set -e 

(! true) # This as a whole is now a failing (compound) command 
echo Exit status: $? 

$ ./exit_on_error_test.sh 
Interrupted because of an error 
$ 
0

set -e命令指示

退出立即如果具有非零状态

一个命令退出(参照help set)。

在Bash中,括号中的表达式创建了一个subshell(子流程),其工作方式与单个命令相似。因此,如果子shell以错误代码退出,父脚本也会退出(由于-e设置)。

因此,如果grep找到\r字符,则子壳以非零状态退出;主脚本也使用此代码退出(由于set -e)。

您的问题的答案为什么需要括号?是:因为您可能想要退出主脚本,如果grep在git控制下的其中一个文件中找到\r字符。