有没有理由不引用变量?

Mec*_*MK1 4 bash

是否有任何正当理由不将所有变量放在引号中的shell脚本中?("不知道更好"在我看来不是正当理由.)

一般来说,引用变量可以确保它们被视为一个变量,如果它们包含空格或其他特殊字符.那么为什么有人会采用"不安全"的方式而不引用变量?

Joh*_*024 11

那么为什么有人会采用"不安全"的方式而不引用变量?

几乎不是正确的事情.通过将变量放在双引号中,shell的新手几乎总能获得更好的服务. 对于高级用户,我可以想到三个可能的例外:

1.您想要路径名扩展.

一个例子可能是:

glob=*.xml
# Do something, possibly creating xml files
rm $glob
Run Code Online (Sandbox Code Playgroud)

这里,路径名扩展glob 不是在定义时rm执行,而是在执行时执行.有时这种后期评估是有益的.

对于bash,可以创建一个数组glob=(*.xml).除非后期评估很重要,否则这种情况可能优于每种情况.

你想要分词.

当您想要与不支持数组的POSIX shell 兼容时,一个示例是处理简单的命令选项:

opts=
[ -f "$onething" ] && opts="-a"
[ -f "$another" ] && opts="$opts -b"
cmd $opts
Run Code Online (Sandbox Code Playgroud)

在这里,单词拆分允许命令cmd查看多个选项.如果$opts在引号中,它只会看到一个字符串.

这种多种选择的方法仅限于简单的选项. 对于bash,可以opts使用数组替换变量,当选项更复杂时,该数组可以更好地工作.但是,POSIX shell不支持命名数组,因此使用这样的变量作为次优解决方案是可行的.

3. Bash的[[

在内部[[...]],您有时可能希望操作员=测试全局匹配.如果是这样,右侧必须不加引号:

$ glob=*.xml
$ [[ file.xml = "$glob" ]] && echo yes
$ [[ file.xml = $glob ]] && echo yes
yes
Run Code Online (Sandbox Code Playgroud)

全球比赛在您需要时很方便.如果你没有期待他们,他们可能是一场灾难.因此,除非您明确需要全局匹配,否则必须引用右侧.

同样,如果您希望=~操作测试正则表达式匹配:

$ regex=fi.*ml
$ [[ file.xml =~ "$regex" ]] && echo yes
$ [[ file.xml =~ $regex ]] && echo yes
yes
Run Code Online (Sandbox Code Playgroud)

(帽子提示:戈登戴维森)