Bash 中单引号和双引号的区别

Difference between single and double quotes in Bash

提问人:jrdioko 提问时间:7/15/2011 最后编辑:Timur Shtatlandjrdioko 更新时间:9/17/2022 访问量:420251

问:

在 Bash 中,单引号 () 和双引号 () 有什么区别?''""

bash shell 引号

评论

3赞 rugk 2/27/2019
另请参阅(潜在的跨站点重复项):“...”、“...”、“$'...' 和 $”...“ 之间有什么区别引号?来自 Unix 和 Linux Stack Exchange
3赞 tripleee 7/22/2020
标题说的是 Bash,但这实际上适用于任何与 Bourne 兼容的 shell(经典的 Bourne shell、POSIX、、和 - 有一些警告 - )。shashdashkshzsh
0赞 kvantour 2/8/2023
相关新闻: 单引号和双引号空字符串之间有语法差异吗?

答:

908赞 Adam Batkin 7/15/2011 #1

单引号不会插入任何内容,但双引号会。例如:变量、反引号、某些转义符等。\

例:

$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")

Bash 手册是这样说的:

3.1.2.2 单引号

将字符括在单引号 () 中可保留引号中每个字符的文本值。单引号之间不得出现单引号,即使前面有反斜杠也是如此。'

3.1.2.3 双引号

将字符括在双引号 () 中将保留引号内所有字符的文本值,但 、 、 和 除外,当启用历史记录扩展时,。字符和在双引号内保留其特殊含义(请参见 Shell 扩展)。仅当后跟以下字符之一时,反斜杠才保留其特殊含义:、、、或换行符。在双引号内,将删除后跟其中一个字符的反斜杠。没有特殊含义的字符前面的反斜杠保持不变。双引号可以在双引号内引用,方法是在它前面加上反斜杠。如果启用,将执行历史记录扩展,除非使用反斜杠对出现在双引号中的出现进行转义。前面的反斜杠不会被删除。"$`\!$`$`"\!!

特殊参数 和 在双引号中具有特殊含义(请参阅 Shell 参数扩展)。*@

评论

101赞 Kellen Stuart 5/11/2018
对于任何不知道“插值”是什么意思的人:en.wikipedia.org/wiki/String_interpolation
1赞 ekiim 3/3/2019
当你使用 git 提供的时,他们建议像这样使用它,git 提示,根据这应该不起作用。变量有什么特别之处吗?或者如果它不进行插值,为什么它会起作用。git_promptPS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ 'PS#
3赞 Adam Batkin 3/4/2019
@ekiim 将确切的文本设置(不变)为 .试着看看我的意思。但在显示之前会进行评估(请参见 bash 手册页中的部分)。要对此进行测试,请尝试 。您将没有提示。然后运行,突然你的提示是“foo”(在设置时已经评估而不是显示,你仍然没有提示)。PS1echo $PS1PS1PROMPTINGPS1='$X'X=fooPS1
1赞 Emmanuel Devaux 7/15/2022
注意:不合法但有效。即使单引号在单引号之间是不合法的,您也可以通过将每个引号替换为不带空格来逃避它。$ name='O'Hara'$ name='O'\''Hara'''\''
0赞 nutty about natty 2/19/2023
在此上下文中,另请参阅:stackoverflow.com/questions/16033158/...stackoverflow.com/a/16033290/2153622
259赞 likso 7/15/2011 #2

如果你指的是当你回显某物时会发生什么,单引号将从字面上回显你之间的东西,而双引号将评估它们之间的变量并输出变量的值。

例如,这个

#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'

将给出这个:

double quotes gives you sometext
single quotes gives you $MYVAR
639赞 codeforester 2/7/2017 #3

公认的答案很棒。我正在制作一个表格,有助于快速理解该主题。解释涉及一个简单的变量以及一个索引数组。aarr

如果我们设置

a=apple      # a simple variable
arr=(apple)  # an indexed array with a single element

然后是第二列中的表达式,我们将得到第三列中显示的结果/行为。第四列解释该行为。echo

# 表达 结果 评论
1 "$a" apple 变量在内部展开""
2 '$a' $a 变量未在内部展开''
3 "'$a'" 'apple' ''里面没有特别的意义""
4 '"$a"' "$a" ""从字面上看,里面是''
5 '\'' 无效 无法逃脱一个内部;使用或(ANSI-C 引用)'''"'"$'\''
6 "red$arocks" red $arocks不膨胀 ;用于保存$a${a}rocks$a
7 "redapple$" redapple$ $后跟 no variable name 的计算结果为$
8 '\"' \" \里面没有特别的意义''
9 "\'" \' \'在里面被解释,但对""'
10 "\"" " \"在里面解释""
11 "*" * glob 在内部不起作用或""''
12 "\t\n" \t\n \t并且内部没有特殊含义或;使用 ANSI-C 引号\n""''
13 "`echo hi`" hi ``并在内部进行评估(反引号保留在实际输出中)$()""
14 '`echo hi`' `echo hi` ``并且不会在内部进行评估(反引号保留在实际输出中)$()''
15 '${arr[0]}' ${arr[0]} 内部无法访问阵列''
16 "${arr[0]}" apple 阵列访问在内部工作""
17 $'$a\'' $a' 单引号可以在 ANSI-C 引号中转义
18 "$'\t'" $'\t' ANSI-C 引用内部不进行解释""
19 '!cmd' !cmd 历史扩展字符在内部被忽略'!'''
20 "!cmd" cmd args 展开到最新的命令匹配"cmd"
21 $'!cmd' !cmd ANSI-C 引号内的历史扩展字符被忽略'!'

另请参阅:

评论

1赞 Snackoverflow 3/2/2018
公认的答案说最后,那么为什么结果呢?The special parameters * and @ have special meaning when in double quotes"*"*
4赞 Charles Duffy 4/21/2018
@Karl-AnderoMere,因为在这种情况下,它们根本没有扩展为参数。 并且是参数扩展。 但事实并非如此。"$@""$*""@""*"
0赞 SantaXL 12/25/2019
我只想指出,在 bash 中“简单变量”也是数组,这与上面的例子相同echo $aecho ${a[0]}
0赞 Lavya 3/30/2020
@codeforester第 3 条中,你说“里面没有特殊含义”,但根据 GNU 手册:“字符'$'和'''在双引号内保留了它们的特殊含义”。而'的特殊含义是保留$的字面值,答案应该是$a。为什么不是这样?
3赞 tripleee 12/17/2020
最好关闭 Csh 样式的历史引用;它们不是很有用,关闭它们可以帮助您避免未加引号的感叹号出现讨厌的错误消息。查看 stackoverflow.com/questions/11816122/echo-fails-event-not-foundevent not found
28赞 SreehariGaddam 7/15/2018 #4

其他人解释得很好,我只想举一些简单的例子。

可以在文本两边使用单引号,以防止 shell 解释任何特殊字符。美元符号、空格、与号、星号和其他特殊字符在括在单引号内时都会被忽略。

echo 'All sorts of things are ignored in single quotes, like $ & * ; |.'

它将给出这个:

All sorts of things are ignored in single quotes, like $ & * ; |.

唯一不能放在单引号内的是单引号。

双引号的作用类似于单引号,但双引号仍然允许 shell 解释美元符号、反引号和反斜杠。众所周知,反斜杠会阻止解释单个特殊字符。如果需要将美元符号用作文本而不是变量,这在双引号中很有用。它还允许对双引号进行转义,因此它们不会被解释为带引号的字符串的末尾。

echo "Here's how we can use single ' and double \" quotes within double quotes"

它将给出这个:

Here's how we can use single ' and double " quotes within double quotes

还可以注意到,撇号(否则会被解释为带引号的字符串的开头)在双引号中被忽略。但是,变量被解释并用双引号内的值替换。

echo "The current Oracle SID is $ORACLE_SID"

它将给出这个:

The current Oracle SID is test

反引号与单引号或双引号完全不同。反引号不是用来防止对特殊字符的解释,而是实际上强制执行它们所包含的命令。执行随附的命令后,其输出将替换原始行中的反引号。举个例子会更清楚。

today=`date '+%A, %B %d, %Y'`
echo $today

它将给出这个:

Monday, September 28, 2015

评论

2赞 Kiteloopdesign 8/10/2022
我喜欢这个答案,因为清楚地表明.让我补充一点,反引号已被弃用,而 $() 与 POSIX 兼容,因此您应该更喜欢后者。The only thing that cannot be put within single quotes is a single quote
0赞 Ben 11/13/2023
这和今天=$(日期...)一样吗?
5赞 a_r 8/19/2018 #5

和 的用法之间有明显的区别。' '" "

当在任何东西周围使用时,没有完成“转换或翻译”。它按原样打印。' '

无论它围绕着什么,都会被“翻译或转化”成它的价值。" "

通过翻译/转换,我的意思是: 单引号内的任何内容都不会“翻译”为它们的值。它们将被当作内部引号。示例: ,然后将在标准输出上生成。而将在标准输出上产生。a=23echo '$a'$aecho "$a"23

评论

0赞 codeforester 8/22/2018
这个答案非常令人困惑,它没有在现有的好答案之上添加任何东西。
2赞 4/10/2019
在我看来,这是一个简短的答案,没有过于冗长,对我来说很容易理解。当说翻译/转换时,它们的意思是双引号将扩展变量,而单引号不会扩展变量。
2赞 tripleee 2/24/2021
您所说的“转换或平移”通常称为插值。表达式只是文字字符串,而将变量的值插值到文字符号之间以及中间有空格的字符串中。'foo $bar baz'foo $bar baz"foo $bar baz"barfoobaz
0赞 a_r 2/25/2021
@tripleee我只是想用最简单的术语来解释。我想清楚的解释比使用正确的“同义词”更重要。它确实在不使用“插值”一词的情况下帮助了人们。
7赞 Inian 1/3/2019 #6

由于这是在 Bash 中处理引号时事实上的答案,因此在处理 shell 中的算术运算符时,我将补充上面答案中遗漏的另一点。

Bash shell 支持两种算术运算方式,一种由内置命令定义,另一种由运算符定义。前者计算算术表达式,而后者更像是复合语句。let$((..))

重要的是要了解,与任何其他 shell 命令一样,使用的算术表达式会经历分词、路径名扩展。因此,需要进行适当的引用和转义。let

使用时请参阅此示例:let

let 'foo = 2 + 1'
echo $foo
3

在这里使用单引号是绝对可以的,因为这里不需要变量扩展。考虑以下情况

bar=1
let 'foo = $bar + 1'

它会惨遭失败,因为下面的单引号不会扩展,需要双引号作为$bar

let 'foo = '"$bar"' + 1'

这应该是原因之一,应该始终考虑过度使用。因为在里面,内容不受分词的影响。前面的例子使用可以简单地写成$((..))letlet

(( bar=1, foo = bar + 1 ))

永远记得不带单引号使用$((..))

虽然可以与双引号一起使用,但它没有任何用途,因为它不能包含需要双引号的内容。只要确保它不是单引号即可。$((..))

printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2

也许在某些特殊情况下,在单引号字符串中使用运算符时,您需要以不加引号或双引号的方式插值引号。例如,考虑一个案例,当您在每次发出请求时都绑定到在语句中使用运算符来传递计数器时,请执行$((..))curl

curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'

请注意,内部使用了嵌套的双引号,如果没有这些引号,文本字符串将传递到字段。$((reqcnt++))requestCounter

评论

2赞 PesaThe 1/7/2019
查尔斯·达菲(Charles Duffy在这里也为双重引用提供了很好的理由。例如,这可能是“有点”偏执狂,而且不太可能有,但这肯定不是不可能:)$((...))IFS=0
0赞 tripleee 11/28/2019
还有遗留语法,但也许你忘记它是对的。$[[...]]
-4赞 user2297550 12/30/2021 #7

人们需要一个最低限度的答案,而不必像我一样花费大量时间。

令人惊讶的是(对于那些寻找答案的人来说),这是一个完整的命令:

$ echo '\'

其输出为:

\

令人惊讶的是,即使是 bash 的长期用户,反斜杠在单引号内没有任何意义。其他任何事情也没有。