&&和|和有什么区别?在bash脚本中?


13

让我们采用下面的两行,这将给我们两个不同的结果。

p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ |  pwd) ; echo $p

两者有何不同?


@heemayl谢谢。您能提取我案件的不同之处吗?谢谢。
Nam G VU

1
提示:左右两边的命令都|在子shell 中运行。
heemayl

Answers:


21

p=$(cd ~ && pwd)

  • 命令替换$()在子外壳中运行

  • cd ~将目录更改为~(您的主目录),如果cd成功(&&),则pwd在STDOUT上打印目录名称,因此保存的字符串p将是您的主目录,例如/home/foobar

p=$(cd ~ | pwd)

  • 再次$()产生一个子壳

  • 两侧的命令|在各自的子shell 中运行(并且两者同时启动)

  • 这样cd ~做是在一个子shell中完成的,并pwd在一个单独的子shell中进行

  • 因此,您只能从pwd运行命令的位置(即从该位置获得STDOUT),这可以是您可以想象的任何目录,因此p将包含从中调用命令的目录名称,而不是您的主目录


命令之间管道的目的是什么?cd ~不产生任何输出,pwd也不读取任何输入。
Barmar

第二个命令本质上等效于(cd ~);p=$(pwd)不是?
Barmar

@Barmar是的,这是OP所使用的,我只是在为他解释一下。
heemayl

7

核心问题是怎么算&&|连接两个命令。

&&通过退出代码的命令连接。在|经由文件描述符(STDIN,STDOUT)这两个命令连接。

让我们先简化一下。我们可以删除任务并写:

echo $(cd ~ && pwd)
echo $(cd ~ | pwd)

我们甚至可以删除命令执行子外壳来分析此问题:

$ cd ~ && pwd
$ cd ~ | pwd

&&

如果我们更改提示以显示执行命令的目录,例如PS1='\w\$ ',我们将看到以下内容:

/tmp/user$ cd ~ && pwd
/home/user
~$ 
  • 该命令cd ~将“当前目录”更改为执行命令(/home/user)的实际用户的主目录。
  • 由于命令结果成功(退出代码0),执行&&之后的下一个命令
  • 并打印“当前工作目录”。
  • 正在运行的shell已将其更改为pwd~如提示符所示~$

如果由于某种原因(目录不存在,权限阻止读取目录)而导致目录更改失败(退出代码不为0),则将不执行下一个命令。

例:

/tmp/user$ false && pwd
/tmp/user$ _ 

退出代码1从false阻止执行下一个命令。

因此,“命令1”的退出代码是影响“命令2”的代码。

现在,整个命令的效果是:

/tmp/user$ echo $(cd ~ && pwd)
/home/user
/tmp/user$ _

目录已更改,但是在子外壳中$(…),将打印更改后的目录/home/user,但在子外壳关闭时会立即将其丢弃。pwd返回到初始目录(/tmp/user)。

|

这是发生了什么:

/tmp/user$ cd ~ | pwd
/tmp/user
/tmp/user$ _

元字符|(不是真正的运算符)向外壳发出信号,以创建所谓的“管道”(以bash表示),管道(|)两侧的每个命令都设置在每个子外壳内,首先是右侧命令,然后,左一个。将/dev/stdin右命令的输入文件描述符()连接到输出描述符(/dev/stdout),然后启动和离开这两个命令进行交互。左命令(cd -)没有输出,右命令(pwd)也没有输入。因此,每个人在各自的子外壳中独立运行。

  • cd ~改变了一个壳的PWD。
  • pwd打印其他子壳的(完全独立的)PWD。

当管道结束时,每个外壳上的更改都将被丢弃,外部子外壳尚未更改pwd。

这就是为什么两个命令仅通过“文件描述符”连接的原因。
在这种情况下,没有发送任何内容,也没有读取任何内容。

整个命令:

$ echo "$(cd ~ | pwd)"

只会打印执行命令的目录。


5

我不确定您的意思是“ |” 或'||' 在第二种情况下。

'|' 在shell中,一个命令的输出通过管道传递给另一个命令的输入-常见的用例是: curl http://abcd.com/efgh | grep ijkl 运行一个命令,然后使用另一个命令来处理命令的输出。

在您给出的示例中,这完全是荒谬的,因为“ cd”通常不会产生任何输出,而“ pwd”不会期望任何输入。

'&&'和'||' 是伙伴命令。在大多数语言中,它们被设计为与逻辑“和”和“或”运算符相同的方式使用。但是,执行的优化为它们提供了一种特定的行为,即Shell编程范例。

要确定逻辑“和”运算的结果,只需要在第一个条件成功的情况下评估第二个条件-如果第一个条件失败,则总结果将始终为false。

要确定逻辑“或”运算的结果,仅在第一个条件失败时才需要评估第二个条件-如果第一个条件成功,则总结果将始终为true。

因此,在shell中,如果您command1 && command2 command2只有在command1完成并返回成功的结果代码后才执行。如果已command1 || command2 command2执行command1完毕,则command1返回失败代码。

另一个常见的范例是command1使用一条测试命令-这将生成一行if / then语句-例如:

[ "$VAR" = "" ] && VAR="Value if empty"

如果变量当前为空,则是一种(长期)将值分配给变量的方法。

在Stack Exchange的其他地方有很多使用此过程的示例

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.