在 Bash 中,我们应该将文件名放在引号还是双引号中?标准是什么?
SRC=file
或者
SRC='file'
或者
SRC="file"
?
答案1
关于变量赋值需要注意的一点是,它们在 shell 语法中有点特殊。根据 Bash 文档,3.7.1 简单命令扩展:
每个变量赋值中' ' 后面的文本
=
在分配给变量之前都会经过波浪符号扩展、参数扩展、命令替换、算术扩展和引号删除。
不过,一般来说,token 也会经历字段拆分和文件名扩展(参见3.5 Shell 扩展), 但这些不是在变量赋值期间执行的。
这意味着未引用 $foo
下列情况,将区别对待:
some-command $foo
bar=$foo
假设foo='/* a b c */'
. (* a b c *
是目录的完全有效名称,因此/* a b c */
也是目录的完全有效路径。)对于some-command $foo
,它首先变得就像您写道:
some-command /* a b c */
然后由 shell 扩展为如下内容:
some-command /bin /boot ... a b c dir1/ dir2/ ...
但对于bar=$foo
,情况并非如此。不会进行字段拆分或文件名扩展,它将保持原样 -bar
将具有值/* a b c */
。但是,如果您随后执行some-other-command $bar
,那么它将进行字段拆分和文件名扩展。
不过,在这两种情况下,引用"$foo"
都会有相同的行为:
some-command "$foo" # no field splitting, no filename expansion
bar="$foo" # equivalent to bar=$foo
一些经验法则:
如果您的值具有 shell 元字符,那么您必须至少引用这些元字符。元字符是:
不加引号时用于分隔单词的字符。元字符是
space
、tab
、newline
或以下字符之一:'|
'、'&
'、';
'、'(
'、')
'、'<
' 或 '>
'。如果值有
!
,并且启用了历史扩展(通常在交互式 shell 中是这种情况),则需要至少引用!
using单引号或反斜杠。双引号不够。如果值有一个
~
,并且你希望波浪符号扩展发生,那么“波浪号前缀” 必须不加引号(所以~/
在 中"/some/path":~/"bar"
,或~user/
在 中~user/".config/app"
,等等)。这使得可以将波浪号扩展与包含空格等的路径混合使用(所以~user/"some path (with metacharacters)"
)。如果值具有参数扩展(
$foo
,,${foo}
等等),或者命令替换($(bar)
,或`foo`
),或者算术扩展($((a+b))
),或者类似于这些的内容,则:- 如果不想执行扩展,请用单引号将它们括起来。您也可以使用反斜杠,但仅仅
$
在 中进行转义是不够的$(
,因为(
如上所述, 是元字符,也需要用引号引起来。 - 如果您希望扩展它们,则可以不引用它们,或者您可以使用双引号。
- 如果不想执行扩展,请用单引号将它们括起来。您也可以使用反斜杠,但仅仅
如果值中包含过程替换(
>(...)
或<(...)
),则仅当替换未加引号时才会执行。
数组与常规赋值不同。通常,(...)
for内部的部分a=(...)
会像命令行中其他任何地方一样进行扩展,因此会执行字段拆分和文件名扩展。这样就可以执行如下操作:
set -f
IFS=:
path=($PATH)
并将条目$PATH
作为数组中的单独项目获取path
。
答案2
没有“标准”Bash 参考手册。
可以通过以下形式的语句来分配变量
name=[value]
引用:
引号用于删除某些字符或单词对 shell 的特殊含义。引号可用于禁用对特殊字符的特殊处理、防止保留字被识别为保留字以及防止参数扩展。
在服务器系统上,默认文件名通常是标准字母数字字符,不包含任何特殊字符,并且应该引用一般来说不需要(尽管有例外可能申请)。
但是在桌面系统上,文件名包含空格和其他特殊字符的情况更常见,然后路径应该用引号引起来 - 这通常被认为是“安全路线”。
如果引用,请使用符合您需求的引号:单引号将按字面意思处理每个字符,而双引号仍将$
、`
和\
视为!
特殊字符。
但是引用的标准与分配变量的语法是分开的,因此它完全取决于变量的上下文(在本例中是文件名)。
答案3
无引号示例:
filePath=Documents Folder 2
echo "$filePath"
这将呼应文件。
第一个空格后的所有内容都将丢失。您需要使用引号来保留空格。不使用引号仅适用于单个单词,但一般来说这不是一个好的做法。无论如何,最好使用引号。
双引号示例:
filePath="$HOME/Documents"
echo "$filePath"
这将呼应/home/用户名/Documents
单引号示例:
filePath='$HOME/Documents'
echo "$filePath"
这将呼应$HOME/文档
如果希望系统按原样使用字符,则使用单引号。
如果希望系统处理变量或其他特殊用途,则使用双引号。
答案4
两者都可以工作,尽管略有不同。最大的区别在于,在单引号之间,大多数 shell 扩展(通配符、变量、命令替换等)都不会发生,因此如果您的文件名包含变量,例如:
$HOME/Documents/myfile.txt
如果您将其放在“单引号”中,那么无论文件名发送到哪个命令/程序,它都会被视为以文字 $ 字符开头,后跟“HOME”。使用“双引号”允许扩展变量名(因此上面的 $HOME 将替换为您的实际主目录),但不能使用通配符,即 * ? [ ] 等。转义空格和其他“分隔符”字符,或在使用通配符之前关闭(单引号或双引号)可使它们正常工作。
另一方面,如果您没有将文件名或应该包含文件名的变量放在引号中,那么包含空格或制表符的任何内容都会被分成几个参数,这通常不是您想要的。