Bash中单引号和双引号的区别
Posted
技术标签:
【中文标题】Bash中单引号和双引号的区别【英文标题】:Difference between single and double quotes in Bash 【发布时间】:2021-08-29 13:56:54 【问题描述】:在 Bash 中,单引号 (''
) 和双引号 (""
) 有什么区别?
【问题讨论】:
另见(可能的跨站点重复):What is the difference between “…”, '…', $'…', and $“…” quotes?,来自 Unix & Linux Stack Exchange。 标题是 Bash,但这确实适用于任何与 Bourne 兼容的 shell(经典 Bourne shell、POSIXsh
、ash
、dash
、ksh
和 - 有一些注意事项- zsh
)。
【参考方案1】:
单引号不会插入任何内容,但双引号会。例如:变量、反引号、某些\
转义等。
例子:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Bash 手册是这样说的:
3.1.2.2 Single Quotes
将字符括在单引号 (
'
) 中会保留引号内每个字符的字面值。单引号之间可能不会出现单引号,即使前面有反斜杠。3.1.2.3 Double Quotes
将字符括在双引号 (
"
) 中会保留引号内所有字符的字面值,$
、`
、\
和启用历史扩展时,@987654334 除外@。字符$
和`
在双引号中保留其特殊含义(请参阅Shell Expansions)。反斜杠仅在后跟以下字符之一时才保留其特殊含义:$
、`
、"
、\
或换行符。在双引号内,将删除后面跟有这些字符之一的反斜杠。没有特殊含义的字符前面的反斜杠保持不变。双引号可以用反斜杠在双引号中引用。如果启用,将执行历史扩展,除非出现在双引号中的!
使用反斜杠转义。!
前面的反斜杠不会被删除。特殊参数
*
和@
在双引号中具有特殊含义(参见Shell Parameter Expansion)。
【讨论】:
对于任何不知道“插值”是什么意思的人:en.wikipedia.org/wiki/String_interpolation 当你使用 git 提供的git_prompt
时,他们建议像这样使用它PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
,git prompt,根据这不应该工作。 PS#
变量有什么特别之处吗?或者如果它不进行插值,为什么它会起作用。
@ekiim 将确切的文本设置(未更改)到PS1
。试试echo $PS1
看看我的意思。但是 PS1
在显示之前会被评估(参见 bash 手册页中的 PROMPTING
部分)。要对此进行测试,请尝试PS1='$X'
。您将没有提示。然后运行X=foo
,突然你的提示是“foo”(如果在 set 而不是 displayed 时评估了PS1
,你仍然没有提示)。【参考方案2】:
accepted answer 很棒。我正在制作一个有助于快速理解该主题的表格。解释涉及到一个简单的变量a
以及一个索引数组arr
。
如果我们设置
a=apple # a simple variable
arr=(apple) # an indexed array with a single element
然后echo
第二列中的表达式,我们将得到第三列中显示的结果/行为。第四列解释了行为。
# | Expression | Result | Comments |
---|---|---|---|
1 | "$a" |
apple |
variables are expanded inside ""
|
2 | '$a' |
$a |
variables are not expanded inside ''
|
3 | "'$a'" |
'apple' |
'' has no special meaning inside ""
|
4 | '"$a"' |
"$a" |
"" is treated literally inside ''
|
5 | '\'' |
invalid | can not escape a ' within '' ; use "'" or $'\'' (ANSI-C quoting) |
6 | "red$arocks" |
red |
$arocks does not expand $a ; use $arocks to preserve $a
|
7 | "redapple$" |
redapple$ |
$ followed by no variable name evaluates to $
|
8 | '\"' |
\" |
\ has no special meaning inside ''
|
9 | "\'" |
\' |
\' is interpreted inside "" but has no significance for '
|
10 | "\"" |
" |
\" is interpreted inside ""
|
11 | "*" |
* |
glob does not work inside "" or ''
|
12 | "\t\n" |
\t\n |
\t and \n have no special meaning inside "" or '' ; use ANSI-C quoting |
13 | "`echo hi`" |
hi |
`` and $() are evaluated inside "" (backquotes are retained in actual output) |
14 | '`echo hi`' |
`echo hi` |
`` and $() are not evaluated inside '' (backquotes are retained in actual output) |
15 | '$arr[0]' |
$arr[0] |
array access not possible inside ''
|
16 | "$arr[0]" |
apple |
array access works inside ""
|
17 | $'$a\'' |
$a' |
single quotes can be escaped inside ANSI-C quoting |
18 | "$'\t'" |
$'\t' |
ANSI-C quoting is not interpreted inside ""
|
19 | '!cmd' |
!cmd |
history expansion character '!' is ignored inside ''
|
20 | "!cmd" |
cmd args |
expands to the most recent command matching "cmd"
|
21 | $'!cmd' |
!cmd |
history expansion character '!' is ignored inside ANSI-C quotes |
另见:
ANSI-C quoting with$''
- GNU Bash Manual
Locale translation with $""
- GNU Bash Manual
A three-point formula for quotes
【讨论】:
接受的答案最后说The special parameters * and @ have special meaning when in double quotes
那么"*"
怎么会导致*
?
@Karl-AnderoMere,因为在这种情况下它们根本没有作为参数展开。 "$@"
和 "$*"
是参数扩展。 "@"
和 "*"
不是。
@CharlesDuffy 谢谢,现在有意义了!
Csh 风格的历史引用可能最好关闭;它们不是很有用,关闭它们可以帮助您避免讨厌的event not found
不带引号的感叹号错误消息。见***.com/questions/11816122/echo-fails-event-not-found
@codeforester 我认为第 14 行的结果应该是 echo hi
被反引号包围。抱歉,我无法在评论中逃避反引号。【参考方案3】:
如果您指的是回显某些内容时会发生什么,单引号将逐字地回显它们之间的内容,而双引号将评估它们之间的变量并输出变量的值。
比如这个
#!/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
【讨论】:
【参考方案4】:别人解释的很好,只想举个简单的例子。
单引号可用于文本周围,以防止外壳解释任何特殊字符。用单引号括起来的美元符号、空格、& 符号、星号和其他特殊字符都将被忽略。
$ 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
【讨论】:
【参考方案5】:由于这是在处理 bash
中的引号时的实际答案,因此在处理 shell 中的算术运算符时,我将在上面的答案中再补充一点。
bash
shell 支持两种算术运算方式,一种由内置的let
命令和$((..))
运算符定义。前者对算术表达式求值,而后者更像是一个复合语句。
重要的是要了解let
使用的算术表达式会像任何其他shell 命令一样经历分词、路径名扩展。因此,需要进行适当的引用和转义。
使用let
时请参阅此示例
let 'foo = 2 + 1'
echo $foo
3
在这里使用单引号绝对没问题,因为这里不需要变量扩展,请考虑
bar=1
let 'foo = $bar + 1'
会惨遭失败,因为单引号下的$bar
不会扩展,需要双引号
let 'foo = '"$bar"' + 1'
这应该是原因之一,应该始终考虑使用$((..))
而不是使用let
。因为在里面,内容不受分词的影响。前面使用let
的例子可以简单写成
(( 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
字段。
【讨论】:
Charles Duffy 为 here 双引号提供了一个很好的案例$((...))
。例如,这可能是“有点”偏执,并且不太可能拥有IFS=0
,但这当然不是不可能的:)
还有旧的$[[...]]
语法,但也许你忘记它是对的。【参考方案6】:
' '
和 " "
的用法有明显区别。
当' '
用于任何事物时,不会进行“转换或翻译”。它按原样打印。
对于" "
,无论它包围什么,都被“转换或转换”为它的值。
通过翻译/转换,我的意思是:
单引号内的任何内容都不会“翻译”为它们的值。它们将被视为在引号内。示例:a=23
,然后echo '$a'
将在标准输出上产生$a
。而echo "$a"
将在标准输出上产生23
。
【讨论】:
这个答案非常令人困惑,它并没有在现有的好答案之上添加任何内容。 在我看来,这是一个简短的回答,不会过于冗长,我很容易理解。当说翻译/转换时,它们的意思是双引号会扩展变量,而单引号不会扩展变量。 您所说的“转换或翻译”通常称为插值。表达式'foo $bar baz'
只是文字字符串foo $bar baz
,而"foo $bar baz"
插值变量 bar
插入到文字符号 foo
和 baz
之间的字符串中,中间有空格。
@tripleee 我只是想用最简单的方式解释一下。而且我想清楚的解释比使用正确的“同义词”更重要。它确实在不使用“插值”一词的情况下帮助了人们。【参考方案7】:
人们需要一个最低限度的答案才能开始工作,而不必像我一样花费大量时间。
令人惊讶的是(对于那些正在寻找答案的人来说)以下是一个完整的命令:
$ echo '\'
谁的输出是:
\
对于 bash 的长期用户来说,反斜杠在单引号内没有任何意义。其他也没有。
【讨论】:
以上是关于Bash中单引号和双引号的区别的主要内容,如果未能解决你的问题,请参考以下文章