以下一系列情况echo $var
可能会显示与刚刚分配的值不同的值。无论分配的值是“双引号”、“单引号”还是未加引号,都会发生这种情况。
我如何让 shell 正确设置我的变量?
星号
预期输出是/* Foobar is free software */
,但我得到的却是一个文件名列表:
$ var="/* Foobar is free software */"
$ echo $var
/bin /boot /dev /etc /home /initrd.img /lib /lib64 /media /mnt /opt /proc ...
方括号
预期值是[a-z]
,但有时我得到的却是一个字母!
$ var=[a-z]
$ echo $var
c
换行符(新行)
预期值是单独行的列表,但所有值都在一行上!
$ cat file
foo
bar
baz
$ var=$(cat file)
$ echo $var
foo bar baz
多个空格
我期望表格标题能够被仔细对齐,但是多个空格要么消失,要么折叠成一个!
$ var=" title | count"
$ echo $var
title | count
标签
我期望两个制表符分隔的值,但我得到的却是两个空格分隔的值!
$ var=$'key\tvalue'
$ echo $var
key value
在上述所有情况下,变量都已正确设置,但未正确读取!正确的方法是在引用时使用双引号:
echo "$var"
这给出了所有示例中的预期值。始终引用变量引用!
为什么?
当变量不被引用时,它将:
- 进行字段拆分,其中值根据空格拆分为多个单词(默认情况下):前:
/* Foobar is free software */
后:/*
,Foobar
,is
,free
,software
,*/
- 每个词都将经历路径名扩展,其中模式被扩展为匹配的文件:前:
/*
后:/bin
,/boot
,/dev
,/etc
,/home
, … - 最后,所有参数都传递给 echo,它会将它们以单个空格分隔开,从而得到
/bin /boot /dev /etc /home Foobar is free software Desktop/ Downloads/
而不是变量的值。
当变量被引用时它将:
- 取代其价值。
- 没有步骤 2。
这就是为什么你应该总是引用所有的变量引用,除非你特别需要分词和路径名扩展。shellcheck 之类的工具可以提供帮助,并会在上述所有情况下对缺少引号发出警告。