bash 什么意思啊!在 shell 中的命令之前?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47261313/
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
What's the meaning of a ! before a command in the shell?
提问by sthzg
The question is in the title. What is the purpose of a shell command (part of a shell script) starting with an exclamation mark? Concrete example:
问题在标题中。以感叹号开头的 shell 命令(shell 脚本的一部分)的目的是什么?具体例子:
In foo.sh:
在 foo.sh 中:
#!/usr/bin/env bash
set -e
! docker stop foo
! docker rm -f foo
# ... other stuff
I know that without the space the exclamation mark is used for history replacements and ! <expression>
according to the man pagecan be used to evaluate "True if expr is false". But in the example context that does not make sense to me.
我知道没有空格,感叹号用于历史替换,并且! <expression>
根据手册页可用于评估“如果 expr 为假则为真”。但是在示例上下文中,这对我来说没有意义。
回答by fedorqui 'SO stop harming'
TL;DR: This is just by-passing the set -e
flag in the specific line where you are using it.
TL;DR:这只是绕过set -e
您使用它的特定行中的标志。
Adding add to hek2mgl's correct and useful answer.
添加添加到hek2mgl 的正确和有用的答案。
You have:
你有:
set -e
! command
Bash Reference Manual → Pipelinesdescribes:
Each command in a pipeline is executed in its own subshell. The exit status of a pipeline is the exit status of the last command in the pipeline (...). If the reserved word ‘!' precedes the pipeline, the exit status is the logical negation of the exit statusas described above. The shell waits for all commands in the pipeline to terminate before returning a value.
管道中的每个命令都在其自己的子 shell 中执行。管道的退出状态是管道中最后一个命令的退出状态(...)。如果保留字 '!' 在管道之前,退出状态是退出状态的逻辑否定,如上所述。shell 在返回值之前等待管道中的所有命令终止。
This means that !
preceding a command is negating the exit status of it:
这意味着!
在命令之前否定它的退出状态:
$ echo 23
23
$ echo $?
0
# But
$ ! echo 23
23
$ echo $?
1
Or:
或者:
$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail
The exit status is useful in many ways. In your script, used together with set -e
makes the script exit whenever a command returns a non-zero status.
退出状态在很多方面都很有用。在您的脚本中,set -e
当命令返回非零状态时,与 with 一起使用会使脚本退出。
Thus, when you have:
因此,当你有:
set -e
command1
command2
If command1
returns a non-zero status, the script will finish and won't proceed to command2
.
如果command1
返回非零状态,脚本将完成并且不会继续command2
。
However, there is also an interesting point to mention, described in 4.3.1 The Set Builtin:
然而,还有一个有趣的点需要提及,在4.3.1 The Set Builtin 中描述:
-e
Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists), or a compound command (see Compound Commands) returns a non-zero status. The shell does not exitif the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, 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 status is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits.
-e
如果管道(请参阅管道)(可能由单个简单命令(请参阅简单命令)、列表(请参阅列表)或复合命令(请参阅复合命令)组成)返回非零状态,则立即退出。如果失败的命令是紧跟在 while 或 until 关键字之后的命令列表的一部分、if 语句中测试的一部分、在 && 或 || 中执行的任何命令的一部分,则shell 不会退出 列表除了最后一个 && 或 || 之后的命令,管道中除最后一个之外的任何命令,或者如果命令的返回状态正在用 ! . 如果子shell 以外的复合命令由于命令在-e 被忽略时失败而返回非零状态,则shell 不会退出。如果设置了 ERR 上的陷阱,则会在 shell 退出之前执行。
Taking all of these into consideration, when you have:
考虑到所有这些,当您有:
set -e
! command1
command2
What you are doing is to by-pass the set -e
flag in the command1
. Why?
你在做什么是绕过set -e
标志的command1
。为什么?
- if
command1
runs properly, it will return a zero status.!
will negate it, butset -e
won't trigger an exit by the because it comes from a return status inverted with !, as described above. - if
command1
fails, it will return a non-zero status.!
will negate it, so the line will end up returning a zero status and the script will continue normally.
- 如果
command1
运行正常,它将返回零状态。!
将否定它,但set -e
不会触发退出,因为它来自与 ! 反转的返回状态,如上所述。 - 如果
command1
失败,它将返回一个非零状态。!
将否定它,因此该行最终将返回零状态并且脚本将正常继续。
回答by hek2mgl
If you don't want the script to fail in both cases, error or success of the command, you can also use this alternative:
如果您不希望脚本在两种情况下都失败,错误或命令成功,您也可以使用此替代方法:
set -e
docker stop foo || true
The boolean or truemakes the pipeline always have 0
as the return value.
boolean或 true使管道始终具有0
作为返回值。