在 shell 脚本中引用变量

Kar*_*rus 10 command-line scripts

在 shell 脚本中,如果我定义了一个变量,例如FOO=25,引用它$FOO$和引用它之间有区别${FOO}$吗?

Aiz*_*ali 16

在大多数情况下,$var${var}是相同的。(请注意,最后一定不能使用 a $!)

需要花括号的一个示例是需要将变量放入连续字符串中。

例子:

var=hel
echo ${var}lo
Run Code Online (Sandbox Code Playgroud)

将输出hello.


ter*_*don 12

回答您的主要问题,${foo}称为“参数扩展”。确切地说,它$本身开始参数扩展,{ }根据POSIX 规范,它们实际上是可选的,但可用于指示变量名称的结尾:

$ foo="bar"
$ echo $fooBaz   ## fails, no variable named $fooBaz exists

$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
Run Code Online (Sandbox Code Playgroud)

基本上,$foo${foo}是相同的。除了上述情况或在进行字符串操作时,它们是完全等效的。

但是,您不应该真正使用它们中的任何一个。经验法则是,除了极少数例外,您应该始终使用"$foo"or"${foo}"并且从不使用$fooor ${foo}。您应该始终引用您的变量以避免调用 split+glob 运算符(稍后会详细介绍)。你当然不想$foo$。最后$是无关紧要的:

$ foo="bar"
$ echo "$foo$"
bar$
Run Code Online (Sandbox Code Playgroud)

所以,虽然不加引号的变量有时是可以的:

$ echo $foo
bar
Run Code Online (Sandbox Code Playgroud)

它们通常不是,应该真正避免:

$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty

$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty
Run Code Online (Sandbox Code Playgroud)

请注意,括号在这里也无济于事:

$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi  ## fails
empty

$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty
Run Code Online (Sandbox Code Playgroud)

当你使用 $foo${foo},shell将拆分(通过设置这是可以改变保存在变量上的空白值IFS变量别的东西)到一个列表,然后在列表中的每个元素被当作一个水珠模式,扩展到任何匹配的文件或目录。这称为split+glob运算符。为了说明,考虑一个包含两个文件的目录:

$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file2
Run Code Online (Sandbox Code Playgroud)

现在,让我们设置一个变量foo *

$ foo="foo *"
Run Code Online (Sandbox Code Playgroud)

如果我们尝试检查具有该名称的文件是否存在会发生什么?

$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
Run Code Online (Sandbox Code Playgroud)

变量被拆分为fooand *,因为它*是一个匹配任何字符串的通配符,所以 shell 会告诉您一个名为foo *exexists.txt的文件。但是,如果我们正确引用它,则不会发生这种情况:

$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
Run Code Online (Sandbox Code Playgroud)

这是一个简单的例子来说明这一点。想象一下,如果我使用了rm而不是echo

所以,第一条规则: 总是引用你的变量。您可以使用"$foo""${foo}"但以任何一种方式引用它。有关安全使用变量的更多详细信息,请查看以下帖子: