将命令放在单引号中对 bash 脚本有任何影响吗?

Does putting a command in single quotes have any effect in a bash script?

我偶然发现了一个脚本,作者在其中将每个外部命令(不是内置命令或函数)放在单引号中。由于我以前从未见过这种编码风格,我想知道以下两个示例之间有什么区别:

'cat' $myfile

对比

cat $myfile

请忽略作者选择不引用保存文件名的变量这一事实。我肯定会把它放在双引号中,我知道变量周围引号的影响。我只对命令周围的引号是否有任何影响感兴趣。这两个例子都很好,但据我所知,单引号在这里是多余的。对吗?

谢谢!

是的,它有效果,但主要是出于一个非常神秘的原因:

考虑一下这个奇怪的结构

alias cat='echo x'
cat foo # would output x foo
'cat' foo # Would output the content of the file foo

将其放在引号内会导致 bash 不会 运行 别名。

也可以达到这种效果
command cat foo # Also outputs the file foo

不同之处在于将命令放在引号中只会跳过别名定义,而使用 command 也会跳过函数定义。由于脚本中通常不启用别名,因此很少使用引号。

在大多数情况下,引用没有空格或特殊字符的字符串等同于根本不引用。

但是,在某些情况下引用会有所不同。

防止别名

许多 linux 发行版自动为 lsgrep 等程序设置别名,例如:

alias ls='ls --color=auto'
alias grep='grep --color=auto'

如果调用引用命令,别名将不会扩展:

ls / # shows the root files and folders with colors
'ls' / # shows the root files and folders without any color

即使部分引用命令也不会使用别名:

'l's / # shows the root files and folders without any color

(不过我强烈建议不要这样做)

保留关键字

有些关键字不能用引号引起来。例如,这将起作用:

time cat $myfile

但这会失败:

'time' cat $myfile

-bash: time: command not found

波浪号扩展

波浪字符 ~ 可用于到达主目录。单独的,它指向当前用户的主目录:

ls ~

当直接跟在用户名后面时,它指向该用户的主目录:

ls ~root

引用波浪号时,目录不会展开,shell 会尝试查找包含波浪号的文件:

ls '~'

ls: cannot access ~: No such file or directory

测试

[[ ]]运算符可以使用test命令,例如-f-e等,但是指令不能被引用。

[[ -e /tmp ]] && echo /tmp exists || echo /tmp is missing

/tmp exists

[[ '-e' /tmp ]] && echo /tmp exists || echo /tmp is missing

-bash: conditional binary operator expected

-bash: syntax error near `/tmp'

结论

在很多情况下,引用确实会有所作为。我觉得第一种情况是你作者写代码的原因。

PS。此列表并不详尽,我特别省略了空格、星号、竖线、& 符号等情况,因为我假设您已经知道为什么有人要引用它们。