为什么我需要括号在bash`set -e`和否定返回码中

Col*_*low 4 linux bash shell xargs

我有一个shell脚本来检查Windows行结尾.

set -e
(! git ls-files | xargs grep -I $'\r')
Run Code Online (Sandbox Code Playgroud)

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

Leo*_*eon 6

你的问题与此无关xargs.

-ebash 的选择有点棘手.

-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
$
Run Code Online (Sandbox Code Playgroud)

因此,即使" ! 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
$ 
Run Code Online (Sandbox Code Playgroud)