有时我看到 shell 脚本使用所有这些不同的方式来引用某些文本:"..."
、'...'
、$'...'
和$"..."
。为什么会使用这么多不同种类的引用?
它们的行为是否有所不同或影响我在它们内部可以做什么?
答案1
所有这些都意味着不同的东西,你可以在其中写不同的东西(或者相同的东西,具有不同的含义)。不同类型的引用解释它们内部的不同转义序列 ( \something
),或者允许或不允许变量插值 ( $something
) 以及它们内部的其他类型的扩展。
简而言之:
'...'
完全是字面意思。"..."
允许变量和嵌入引号字符。$'...'
执行字符转义\n
,但不扩展变量。$"..."
用于 Bash 和 ksh 中的人类语言翻译。
'单引号'
无论您在单引号之间写入什么内容,都会按字面意思进行处理,根本不会进行处理。反斜杠和美元符号在那里没有特殊含义。这意味着您不能反斜杠转义字符(包括其他单引号!)、插入变量或使用任何其他 shell 功能。
所有这些示例都会导致引号之间所写内容的字面意思:
代码 | 结果 |
---|---|
'hello world' |
你好世界 |
'/pkg/bin:$PATH' |
/pkg/bin:$PATH |
'hello\nworld' |
你好\n世界 |
'`echo abc`' |
`回显 abc` |
'I\'dn\'t've' |
我没有 |
最后一项比较复杂——有二单引号字符串与一些不带引号的文本一起运行。第一个包含I\
.未加引号的文本dn\'t
包含转义的单引号在外壳层,因此它不会以带引号的字符串开头,而是作为文字字符包含在内(因此,dn't
)。最终引用的字符串只是ve
.所有这些都按照 shell 的通常工作方式组合成一个单词。
组合文字文本和变量的一种常见习惯用法是将它们一起运行,如下所示:
'let x="'$PATH\"
将导致
let x="/usr/bin:/bin"
作为一个单词(最好$PATH
也用双引号引起来,以防万一 -变量中的空格或通配符价值可能会以其他方式处理- 但为了一个可读的运行示例,我没有)。
“双引号”
在双引号内,会处理两种扩展,您可以使用反斜杠转义字符,以防止处理扩展或转义。
双引号内发生两类扩展:
- 那些以
$
(参数扩展$abc
和${abc}
,命令替换$(...)
, 和算术展开$((...))
); - 带反引号的命令替换
`abc`
;
在引号内,反斜杠可以通过将其放在$
or之前来抑制这些扩展`
。它还可以转义右双引号,因此\"
仅包含"
在字符串或另一个反斜杠中。就像在引号之外\
后跟换行符一样,被视为行延续(已有效删除)。任何其他反斜杠都按字面意思保留 - 没有转义来生成其他字符,并且不会将其删除。
其中一些示例的行为与之前不同,有些则没有:
代码 | 结果 |
---|---|
"hello world" |
你好世界 |
"/pkg/bin:$PATH" |
/pkg/bin:/bin:/usr/bin |
"hello\nworld" |
你好\n世界 |
"hello\\nworld" |
你好\n世界 |
"`echo abc`" |
ABC |
"I\'dn\'t've" |
我没有 |
"I'dn't've" |
我没有 |
"I\"dn\"t've" |
我没有 |
$'ANSI-C 引用'
这种引用允许处理 C 风格的反斜杠转义,但是不是嵌入变量或替换。这是仅有的支持字符转义的引用类型。
这是 ksh 的扩展,现在 Bash、zsh 和其他一些 shell 也支持。它不是然而它是 POSIX 标准的一部分,因此最大可移植脚本无法使用它,但 Bash 或 ksh 脚本可以自由使用。
所有这些转义符都可以按其 C 含义使用:\a
、\b
、\f
、\n
、\r
、\t
、\v
、 和字面转义符\\
、\'
、\"
和\?
。它们还支持扩展\e
(转义字符)以及 Bash 和 ksh 中的扩展\cx
(将输入的内容)通过 Ctrl-x,例如\cM
是回车)。 Shell 有一系列自己的小扩展。
它还允许四种通用字符转义:
\nnn
,具有八进制值的单个字节恩恩\xHH
, 具有十六进制值的单个字节赫赫\uHHHH
,十六进制索引为的 Unicode 代码点呵呵呵呵\UHHHHHHHH
,十六进制索引为的 Unicode 代码点哈哈哈哈哈哈
第一个数字之后的所有这些数字都是可选的。
$
并且`
没有任何意义并且按字面意思保留,因此不能在其中包含变量。
代码 | 结果 |
---|---|
$'hello world' |
你好世界 |
$'/pkg/bin:$PATH' |
/pkg/bin:$PATH |
$'hello\nworld' |
你好 世界 |
$'`echo abc`' |
`回显 abc` |
$'I\'dn\'t\'ve' |
我没有 |
$'\U1f574\u263A' |