之间有什么区别:
set -e;
./create-git-tag.sh || {
echo 'Could not create git tag.'
exit 1;
}
和
set -e;
if ! ./create-git-tag.sh; then
echo 'Could not create git tag.'
exit 1;
fi
我猜测 if 块不会创建子 shell,因此会在输入 if 块之前退出?它们看起来功能相同,行为上有什么差异吗?
答案1
大括号{ }
不会创建子 shell,圆括号会创建:
重击(1)
(列表)
list 在子shell 环境中执行。
{列表;}
list 只是在当前 shell 环境中执行。
因此,if
语句和表单都... || { }
没有创建子 shell 的潜力。
子shell环境可能( )
如果使用圆括号而不是大括号来创建。仅当第一个命令||
返回非零状态(IE。./create-git-tag.sh 失败)。
如果set -e
使用,所有形式都表现出相同的行为(当测试命令失败时,shell 立即退出) - 但在幕后,圆括号将创建一个子 shell(在本示例中似乎没有用)。
如果set -e
不是使用,创建子 shell( )
意味着子 shell 将退出,但调用 shell 将继续 - 后面的命令仍将被执行。
在所有情况下,只有在测试命令失败时才会输入 echo-exit 命令链(以及圆括号的关联子 shell)。但是制作条件逻辑的目的是某些东西可能会失败,也可能不会 - 这就是你在问题中的措辞没有意义的地方:
我猜测 if 块不会创建子 shell,因此会在输入 if 块之前退出?
if 块是“进入”后,它会运行测试命令来确定下一步要做什么。
就我个人而言,我发现该if
语句更易于阅读,并且更喜欢在脚本中使用它。当我“交互”使用 shell 时,操作员&&
和||
我可能会使用 in 。if
答案2
我的理解是它们是等价的;在这两种情况下,exit
都会终止运行脚本的 shell 实例。
您所拥有的两个版本都不会创建子shell。为了证明这一点,请考虑以下实验:
$ cat version1
#!/bin/bash
set -e
x=7
ls /tmp/does/not/exist &> /dev/null || {
x=42
}
echo $x
$ ./version1
42
$ cat version2
#!/bin/bash
set -e
x=7
if [ ! ls /tmp/does/not/exist &> /dev/null ]; then
x=42
fi
echo $x
$ ./version2
42
如果将{ }
in更改version1
为()
(如以下版本所示),则会创建一个子 shell。因此,x
内部的修改( )
不会影响x
调用 shell:
$ cat version3
#!/bin/bash
set -e
x=7
ls /tmp/does/not/exist 2> /dev/null || (
x=42
)
echo $x
$ ./version3
7