为什么我需要括号在 bash `set -e` 和否定返回码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39581150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do I need parenthesis In bash `set -e` and negated return code
提问by Colton Leekley-Winslow
I have a shell script which checks for windows line endings.
我有一个 shell 脚本来检查 windows 行尾。
set -e
(! git ls-files | xargs grep -I $'\r')
I am using the !
character to negate the return code of the command. Grep will return code 0
when a file with carriage return is found, and !
negates the value to the return code is then 1
and the script exits. When used with grep
(no xargs
) this works without parentheses. When xargs
is used the negation takes place according to $?
, as echo $?
will print 1
, however the script does not exit! After adding parentheses around the whole command, it works as expected. Why are the parentheses needed?
我正在使用该!
字符来否定命令的返回码。0
当找到带回车的文件时,Grep 将返回代码,并!
否定返回代码的值,然后1
脚本退出。当与grep
(no xargs
)一起使用时,它无需括号即可工作。当xargs
使用否定根据发生$?
,如echo $?
将打印1
,但是脚本不会退出!在整个命令周围添加括号后,它按预期工作。为什么需要括号?
回答by Leon
Your problem has nothing to do with xargs
.
你的问题与xargs
.
The -e
option of bash is a little tricky.
-e
bash的选项有点棘手。
-eExit immediately if a pipeline(which may consist of a single simple command), a list, or a compound command, exits with a non-zero status. The shell does not exitif the command that fails is part of the command list immediately following a
while
oruntil
keyword, part of the test following theif
orelif
reserved words, part of any command executed in a&&
or||
list except the command following the final&&
or||
, any command in a pipeline but the last, or if the command's return value is being inverted with!
.
-e如果管道(可能由单个简单命令组成)、列表或复合命令以非零状态退出,则立即退出。 壳不退出如果失败的命令是紧跟在所述命令列表的一部分
while
或until
关键字,继该测试的一部分if
或elif
保留字,在执行任何命令的一部分&&
或||
除命令列表以下的最终&&
或||
,任何命令在管道中但最后一个,或如果命令的返回值与!
.
Let's look at a much simpler example:
让我们看一个更简单的例子:
$ 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
$
So, even though the exit status of "! true
" was non-zero, the script was allowed to run to the end and output the value of the exit status. That's because we didn't have any failing command - the non-zero exit code was due to deliberate negation.
因此,即使 " ! true
"的退出状态不为零,脚本也可以运行到最后并输出退出状态的值。那是因为我们没有任何失败的命令——非零退出代码是由于故意否定。
However, if we enclose "! true
" in parentheses we introduce a failing (compound) command.
但是,如果我们将“ ! 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
$
回答by Ruslan Osmanov
The set -e
command instructs to
该set -e
命令指示
Exit immediately if a command exits with a non-zero status
如果命令以非零状态退出,则立即退出
(see help set
).
(见help set
)。
In Bash, an expression in parentheses creates a subshell(subprocess), which works like a single command. Thus, if a subshell exits with an error code, the parent script exits, too (due to the -e
setting).
在 Bash 中,括号中的表达式会创建一个子 shell(子进程),其工作方式类似于单个命令。因此,如果子 shell 以错误代码退出,父脚本也会退出(由于-e
设置)。
So if grep
finds the \r
character, the subshell exits with non-zero status; the main script exits with this code, too (due to set -e
).
因此,如果grep
找到该\r
字符,则子shell 以非零状态退出;主脚本也使用此代码退出(由于set -e
)。
The answer to your question Why are the parentheses needed?is: because you probably want to exit the main script, if grep
finds a \r
character in one of the files under git control.
问题的答案为什么需要括号?是:因为你可能想退出主脚本,如果在 git 控制下的文件之一中grep
找到一个\r
字符。