Answers:
在大多数情况下,$var
和${var}
都是相同的。(请注意,$
最后不能使用a !)
需要大括号的一个示例是需要将变量放入连续字符串中。
例:
var=hel
echo ${var}lo
将输出hello
。
要回答您的主要问题,${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
基本上$foo
和${foo}
相同。除了上述情况或进行字符串操作时,它们是完全等效的。
但是,您不应该真正使用它们中的任何一个。经验法则是,除了极少数例外,您应该始终使用"$foo"
or,"${foo}"
并且永远不要使用$foo
or ${foo}
。您应该始终引用变量,以避免调用split + glob运算符(稍后会详细介绍)。你当然不想$foo$
。最终$
是无关紧要的:
$ foo="bar"
$ echo "$foo$"
bar$
因此,虽然未引用变量有时可以:
$ echo $foo
bar
通常不是,应该避免使用它们:
$ 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
请注意,括号在这里也无济于事:
$ 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
当您使用$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
现在,让我们将变量设置为foo *
:
$ foo="foo *"
如果我们尝试检查具有该名称的文件会发生什么?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
变量被拆分为foo
和,*
并且由于*
是与任何字符串匹配的通配符,因此Shell会告诉您一个名为foo *
exxists 的文件。但是,如果我们正确引用它,则不会发生:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
这是一个微不足道的例子来说明这一点。试想一下,如果我使用过rm
而不是echo
。
因此,第一个规则:总是引用变量。您可以使用"$foo"
或"${foo}"
两种方式引用。有关安全使用变量的更多详细信息,请查看以下文章:
$ var="foo *"
应该$ foo="foo *"
吗?您不会var
在任何地方使用。
$
最终不要使用!它将被视为普通字符,而不是变量名的一部分。