为什么我需要括号 In bash `set -e` 和否定 return 代码
Why do I need parenthesis In bash `set -e` and negated return code
我有一个 shell 脚本来检查 windows 行结尾。
set -e
(! git ls-files | xargs grep -I $'\r')
我正在使用 !
字符来否定命令的 return 代码。 Grep 将 return 代码 0
当找到带有回车符 return 的文件时,并且 !
否定 return 代码的值然后 1
并且脚本退出。当与 grep
一起使用时(没有 xargs
),这可以在没有括号的情况下工作。当使用 xargs
时,根据 $?
进行否定,因为 echo $?
将打印 1
,但脚本不会退出!在整个命令周围添加括号后,它按预期工作。为什么需要括号?
set -e
命令指示
Exit immediately if a command exits with a non-zero status
(参见 help set
)。
在 Bash 中,括号中的表达式创建一个 subshell(子进程),其工作方式类似于单个命令。因此,如果子 shell 以错误代码退出,则父脚本也会退出(由于 -e
设置)。
因此,如果 grep
找到 \r
字符,子 shell 将以非零状态退出;主脚本也使用此代码退出(由于 set -e
)。
你的问题为什么需要括号?的答案是:因为你可能想退出主脚本,如果grep
找到一个\r
字符在 git 控制下的其中一个文件中。
您的问题与xargs
无关。
bash的-e
选项有点棘手。
-e Exit 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 exit if the command that
fails is part of the command list immediately
following a while
or until
keyword, part of the test
following the if
or elif
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 !
.
让我们看一个更简单的例子:
$ 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
$
我有一个 shell 脚本来检查 windows 行结尾。
set -e
(! git ls-files | xargs grep -I $'\r')
我正在使用 !
字符来否定命令的 return 代码。 Grep 将 return 代码 0
当找到带有回车符 return 的文件时,并且 !
否定 return 代码的值然后 1
并且脚本退出。当与 grep
一起使用时(没有 xargs
),这可以在没有括号的情况下工作。当使用 xargs
时,根据 $?
进行否定,因为 echo $?
将打印 1
,但脚本不会退出!在整个命令周围添加括号后,它按预期工作。为什么需要括号?
set -e
命令指示
Exit immediately if a command exits with a non-zero status
(参见 help set
)。
在 Bash 中,括号中的表达式创建一个 subshell(子进程),其工作方式类似于单个命令。因此,如果子 shell 以错误代码退出,则父脚本也会退出(由于 -e
设置)。
因此,如果 grep
找到 \r
字符,子 shell 将以非零状态退出;主脚本也使用此代码退出(由于 set -e
)。
你的问题为什么需要括号?的答案是:因为你可能想退出主脚本,如果grep
找到一个\r
字符在 git 控制下的其中一个文件中。
您的问题与xargs
无关。
bash的-e
选项有点棘手。
-e Exit 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 exit if 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!
.
让我们看一个更简单的例子:
$ 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
$