fsgdfgdfgd Asked: 2023-11-20 02:44:57 +0800 CST2023-11-20 02:44:57 +0800 CST 2023-11-20 02:44:57 +0800 CST 我们应该将 Bash 中的文件名放在引号中还是双引号中?标准是什么? 772 我们应该将 Bash 中的文件名放在引号中还是双引号中?标准是什么? SRC=file 或者 SRC='file' 或者 SRC="file" ? bash 3 个回答 Voted muru 2023-11-20T14:06:35+08:002023-11-20T14:06:35+08:00 关于变量赋值需要注意的一件事是它们是 shell 语法中的一种特殊情况。来自 Bash 文档,在3.7.1 简单命令扩展中: 每个变量赋值中“ ”后面的文本=在赋值给变量之前都会经历波形符扩展、参数扩展、命令替换、算术扩展和引号删除。 然而,一般来说,令牌也会经历字段分割和文件名扩展(参见3.5 Shell 扩展),但这些不会在变量 asisgnment 期间执行。 这意味着在以下情况下,未引用的内容会受到不同的处理: $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 中通常是这种情况),则至少需要!使用单引号或反斜杠来引用。双引号是不够的。 如果该值具有 a~并且您希望进行波形符扩展,则“波形符前缀” 必须不加引号(因此~/in "/some/path":~/"bar"、 或~user/in~user/".config/app"等)。这使得可以将波形符扩展与包含空格等的路径混合在一起(so ~user/"some path (with metacharacters)")。 如果该值具有参数扩展($foo、${foo}等)、命令替换($(bar)、 或`foo`)、算术扩展($((a+b)))或类似的内容,则: 如果您不想执行扩展,请用单引号将它们引起来。$您还可以使用反斜杠,但是仅仅在 中转义是不够的$(,(如上所述,元字符也是如此,也需要用引号引起来。 如果您希望扩展它们,则不引用它们也可以,或者您可以使用双引号。 如果该值中有过程替换(>(...)或<(...)),则仅当替换未加引号时才会执行。 数组与常规赋值是不同的游戏。(...)一般来说, for内部的部分a=(...)就像命令行中其他任何地方一样被扩展,因此执行字段分割和文件名扩展。这使得可以执行以下操作: set -f IFS=: path=($PATH) $PATH并将条目作为数组中的单独项目获取path。 Stormlord 2023-11-20T08:16:19+08:002023-11-20T08:16:19+08:00 无引号示例: filePath=Documents Folder 2 echo "$filePath" 这将回显Documents。 第一个空格之后的所有内容都将丢失。您需要引号才能保留空格。不使用引号仅适用于单个单词,但通常不被认为是一个好的做法。无论如何,最好使用引号。 双引号示例: filePath="$HOME/Documents" echo "$filePath" 这将回显/home/用户名/Documents 单引号示例: filePath='$HOME/Documents' echo "$filePath" 这将回显$HOME/Documents 如果您希望系统按原样使用字符,请使用单引号。 如果您希望系统处理变量或其他特殊用途,请使用双引号。 Best Answer Artur Meinild 2023-11-20T02:59:30+08:002023-11-20T02:59:30+08:00 根据Bash 参考手册,没有“标准” 。 变量(Shell 参数): 可以通过以下形式的语句将变量赋值给 name=[value] 引用: 引用用于删除某些字符或单词对 shell 的特殊含义。引号可用于禁用对特殊字符的特殊处理,以防止保留字被识别为此类,并防止参数扩展。 在服务器系统上,默认文件名通常是标准字母数字字符,不包含任何特殊字符,并且通常不需要引用(尽管可能存在例外)。 然而,在桌面系统上,更常见的是文件名包含空格和其他特殊字符,然后应该引用路径 - 这通常被认为是“安全路径”。 如果引用,请使用符合您需要的引号:单引号将按字面意思对待每个字符,而双引号仍会将$, `,\和!视为特殊字符。 但是引用的标准对于分配变量的语法是不同的,因此它完全取决于变量的上下文(在本例中为文件名)。
关于变量赋值需要注意的一件事是它们是 shell 语法中的一种特殊情况。来自 Bash 文档,在3.7.1 简单命令扩展中:
然而,一般来说,令牌也会经历字段分割和文件名扩展(参见3.5 Shell 扩展),但这些不会在变量 asisgnment 期间执行。
这意味着在以下情况下,未引用的内容会受到不同的处理:
$foo
这么说吧
foo='/* a b c */'
。(* a b c *
是一个完全有效的目录名称,因此/* a b c */
也是一个完全有效的目录路径。) 对于some-command $foo
,它首先变得好像您编写了:然后由 shell 扩展为:
但对于 来说
bar=$foo
,情况并非如此。字段分割和文件名扩展都不会完成,并且它将保持原样 -bar
将具有值/* a b c */
。但是,如果您随后这样做some-other-command $bar
,那么它将进行字段分割和文件名扩展。不过,在这两种情况下,引用
"$foo"
都会有相同的行为:一些经验法则:
如果您的值具有 shell 元字符,那么您必须至少引用这些元字符。元字符是:
如果该值具有
!
, 并且启用了历史扩展(交互式 shell 中通常是这种情况),则至少需要!
使用单引号或反斜杠来引用。双引号是不够的。如果该值具有 a
~
并且您希望进行波形符扩展,则“波形符前缀” 必须不加引号(因此~/
in"/some/path":~/"bar"
、 或~user/
in~user/".config/app"
等)。这使得可以将波形符扩展与包含空格等的路径混合在一起(so~user/"some path (with metacharacters)"
)。如果该值具有参数扩展(
$foo
、${foo}
等)、命令替换($(bar)
、 或`foo`
)、算术扩展($((a+b))
)或类似的内容,则:$
您还可以使用反斜杠,但是仅仅在 中转义是不够的$(
,(
如上所述,元字符也是如此,也需要用引号引起来。如果该值中有过程替换(
>(...)
或<(...)
),则仅当替换未加引号时才会执行。数组与常规赋值是不同的游戏。
(...)
一般来说, for内部的部分a=(...)
就像命令行中其他任何地方一样被扩展,因此执行字段分割和文件名扩展。这使得可以执行以下操作:$PATH
并将条目作为数组中的单独项目获取path
。无引号示例:
这将回显Documents。
第一个空格之后的所有内容都将丢失。您需要引号才能保留空格。不使用引号仅适用于单个单词,但通常不被认为是一个好的做法。无论如何,最好使用引号。
双引号示例:
这将回显/home/用户名/Documents
单引号示例:
这将回显$HOME/Documents
如果您希望系统按原样使用字符,请使用单引号。
如果您希望系统处理变量或其他特殊用途,请使用双引号。
根据Bash 参考手册,没有“标准” 。
变量(Shell 参数):
引用:
在服务器系统上,默认文件名通常是标准字母数字字符,不包含任何特殊字符,并且通常不需要引用(尽管可能存在例外)。
然而,在桌面系统上,更常见的是文件名包含空格和其他特殊字符,然后应该引用路径 - 这通常被认为是“安全路径”。
如果引用,请使用符合您需要的引号:单引号将按字面意思对待每个字符,而双引号仍会将
$
,`
,\
和!
视为特殊字符。但是引用的标准对于分配变量的语法是不同的,因此它完全取决于变量的上下文(在本例中为文件名)。