我知道单引号不会评估里面的内容,而双引号会。我经常看到人们引用美元符号的评价。这里有些例子:
for i in "${indices[@]}"; do
if [ "${a}" == 0 ]; then
ffmpeg -framerate 2 -pattern_type glob -i "*.png" -pix_fmt yuv420p output.mp4
如果我们不对美元符号表达式加双引号怎么办? AFAIK,for
循环仍然有效。
答案1
你的三个例子并不完全相同。
在最后两个中:
if [ "${a}" == 0 ]; then
ffmpeg -framerate 2 -pattern_type glob -i "*.png" -pix_fmt yuv420p output.mp4
如果$a
没有加引号,并且其值包含字符$IFS
(默认情况下为空格、制表符和换行符)或通配符,则会导致[
接收超过三个参数(除了[
和]
之外),从而导致错误;类似地,如果的值$a
是空字符串,则会导致
[
接收的参数太少:
$ (a=0; [ $a == 0 ] && echo OK)
OK
(但前提是$IFS
当前恰好不包含0
)
$ (a='foo bar'; [ $a == 0 ] && echo OK)
bash: [: too many arguments
(默认值为$IFS
)
$ (a=; [ $a == 0 ] && echo OK)
bash: [: ==: unary operator expected
(即使使用空$IFS
或 with zsh
(否则不会在不带引号的扩展上实现隐式 split+glob 运算符))
$ (a='*'; [ $a == 0 ] && echo OK)
bash: [: too many arguments
(当在至少包含 2 个非隐藏文件的目录中运行时)。
通过引用,没有错误:
$ (a='foo bar'; [ "$a" == 0 ] && echo OK)
$ (a=; [ "$a" == 0 ] && echo OK)
你的第一个例子是不同的。当涉及数组时,双引号内扩展的规则是特殊的;如果a
表示一个数组,则:
$a
是数组的第一个元素(严格来说,${a[0]}
即使索引 0 处的元素未定义也是如此);${a[*]}
或${a[@]}
是数组的元素,另外在$IFS
(默认情况下为空格、制表符、换行符)处分割;"${a[@]}"
是数组的元素,未在 处分割$IFS
。
因此,您的循环for i in "${indices[@]}"; do ...
实际上并不相同,具体取决于数组的内容。例如:
$ (declare -a a=(a b c); printf '%s\n' $a)
a
$ (declare -a a=(a b c); printf '%s\n' ${a[*]})
a
b
c
$ (declare -a a=(a 'b c'); printf '%s\n' ${a[*]})
a
b
c
$ (declare -a a=(a 'b c'); printf '%s\n' ${a[@]})
a
b
c
$ (declare -a a=(a 'b c'); printf '%s\n' "${a[*]}")
a b c
$ (declare -a a=(a 'b c'); printf '%s\n' "${a[@]}")
a
b c
答案2
长话短说,这样做是为了避免变量中可能存在的特殊字符(如)造成的扩展!
。双引号也称为“弱引用”,因为某些字符将被解释(美元符号、反引号和反斜杠)。单引号是“强引用”,不会解释任何内容。
引用bash 文档:
3.1.2.3 双引号
将字符括在双引号 ( ) 中会保留引号内所有字符的字面值,但、 、和(启用历史扩展时)
"
除外。当 shell 处于 POSIX 模式时(请参阅 Bash POSIX 模式),双引号内的 没有特殊含义,即使启用了历史扩展...$
backquote
\
!
!
弱引用和强引用的示例:
echo "Your PATH is: $PATH"
- 将打印Your PATH is:<variable_content>
echo 'Your PATH is: $PATH'
- 将打印Your PATH is: $PATH
回答您的问题,我们对变量使用双引号以允许$
扩展,但避免变量内容进一步扩展。
相关内容: