!的含义是什么!在Shell中执行命令之前? [英] What's the meaning of a ! before a command in the shell?

查看:146
本文介绍了!的含义是什么!在Shell中执行命令之前?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题在标题中.以感叹号开头的shell命令(shell脚本的一部分)的目的是什么?具体示例:

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:

在foo.sh中:

#!/usr/bin/env bash
set -e
! docker stop foo
! docker rm -f foo
# ... other stuff

我知道,没有空格,根据! <expression>. >手册页可用于评估"如果expr为假,则为真".但是在示例上下文中,这对我来说没有意义.

I know that without the space the exclamation mark is used for history replacements and ! <expression> according to the man page can be used to evaluate "True if expr is false". But in the example context that does not make sense to me.

推荐答案

TL; DR:这只是在使用它的特定行中绕过set -e标志.

TL;DR: This is just by-passing the set -e flag in the specific line where you are using it.

将添加内容添加到 hek2mgl的正确且有用的答案.

您有:

set -e
! command

Bash参考手册→管道描述:

管道中的每个命令都在其自己的子Shell中执行.管道的退出状态是管道中最后一条命令的退出状态(...). 如果保留字词!"在管道之前,则退出状态是退出状态的逻辑取反,如上所述. Shell等待管道中的所有命令终止,然后返回值.

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 status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.

这意味着在命令前的!否定了该命令的退出状态:

This means that ! preceding a command is negating the exit status of it:

$ echo 23
23
$ echo $?
0
                # But
$ ! echo 23
23
$ echo $?
1

或者:

$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail

退出状态在许多方面都很有用.在脚本中,与set -e一起使用会使脚本在命令返回非零状态时退出.

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
command1
command2

如果command1返回非零状态,则脚本将完成并且不会继续执行command2.

If command1 returns a non-zero status, the script will finish and won't proceed to command2.

但是,还有一个值得一提的有趣之处,如

However, there is also an interesting point to mention, described in 4.3.1 The Set Builtin:

-e

如果可能由单个简单命令(请参见简单命令"),列表(请参见列表")或复合命令(请参见复合命令")组成的管道(请参见"Pipelines")返回非零状态,则立即退出. 如果失败的命令紧随一会儿或直到关键字,if语句中的测试部分以及在&& amp;中执行的任何命令的一部分之后的命令列表中的一部分,则外壳程序不会退出 ;或||列表,除了最后一个&&之后的命令或||,管道中除最后一个命令之外的任何命令,或者如果该命令的返回状态已被!反转.如果除子Shell之外的复合命令由于在-e被忽略时命令失败而返回非零状态,则该Shell不会退出.在退出外壳程序之前,将执行ERR上的陷阱(如果已设置).

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 exit if 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.


在以下情况下,请考虑所有这些因素:


Taking all of these into consideration, when you have:

set -e
! command1
command2

您正在做的是绕过command1中的set -e标志.为什么?

What you are doing is to by-pass the set -e flag in the command1. Why?

  • 如果command1运行正常,它将返回零状态. !将使它无效,但是set -e不会触发退出,因为如上所述,它来自返回状态为!的返回状态.
  • 如果command1失败,它将返回非零状态. !将对其进行否定,因此该行最终将返回零状态,并且脚本将继续正常运行.
  • if command1 runs properly, it will return a zero status. ! will negate it, but set -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.

这篇关于!的含义是什么!在Shell中执行命令之前?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆