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

jrd*_*oko 501 syntax bash shell quotes

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

Ada*_*kin 509

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

例:

$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Run Code Online (Sandbox Code Playgroud)

Bash手册有这样的说法:

3.1.2.2单引号

用单引号(')括起字符可以保留引号中每个字符的字面值.单引号之间可能不会出现单引号,即使前面有反斜杠也是如此.

3.1.2.3双引号

在双引号包围字符(")保留了引号中的所有字符的字面意义,例外$,`,\,和,启用了历史扩展的时候,!.字符$`在双引号内保留其特殊含义(请参阅Shell Expansions).:反斜杠后跟当由下列字符只保留它的特殊含义$,`,",\,或换行.在双引号内,将删除后跟其中一个字符的反斜杠.没有特殊含义的字符前面的反斜杠不做修改.双引号可以在双引号内引用,前面加一个反斜杠.如果启用,将执行历史记录扩展,除非!使用反斜杠转义出现在双引号中.之前的反斜杠!不会被删除.

双引号时的特殊参数*@特殊含义(参见Shell参数扩展).

  • 对于任何不知道"插值"意味着什么的人:https://en.wikipedia.org/wiki/String_interpolation (27认同)
  • @ekiim 将确切的文本设置(未更改)到“PS1”中。试试 `echo $PS1` 看看我的意思。但是在显示之前会评估“PS1”(请参阅​​ bash 联机帮助页中的“PROMPTING”部分)。要测试这一点,请尝试`PS1='$X'`。你不会有任何提示。然后运行`X=foo`,突然你的提示是“foo”(如果在*set*而不是*displayed*时评估`PS1`,你仍然没有提示)。 (3认同)

lik*_*kso 219

如果您指的是当您回显某些内容时会发生什么,单引号将直接回显它们之间的内容,而双引号将评估它们之间的变量并输出变量的值.

例如,这个

#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'
Run Code Online (Sandbox Code Playgroud)

会给这个:

double quotes gives you sometext
single quotes gives you $MYVAR
Run Code Online (Sandbox Code Playgroud)


cod*_*ter 217

接受的答案是伟大的.我正在制作一个有助于快速理解主题的表格.解释涉及一个简单的变量a以及一个索引数组arr.

如果我们设定

a=apple      # a simple variable
arr=(apple)  # an indexed array with a single element
Run Code Online (Sandbox Code Playgroud)

然后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 ${a}rocks 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 ""
14 | '`echo hi`' | `echo hi`   | `` and $() are not evaluated inside ''
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
---+-------------+-------------+--------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

也可以看看:

  • Csh 风格的历史引用可能最好关闭;它们不是很有用,关闭它们可以帮助您避免因未加引号的感叹号而出现令人讨厌的“未找到事件”错误消息。请参阅/sf/ask/827128571/ (3认同)
  • @ Karl-AnderoMere,因为在这种情况下它们根本没有扩展为参数.`"$ @"`和`"$*"`是参数扩展.`"@"`和`"*"`不是. (2认同)
  • 数字9,“ echo“ \'”`,传回给我`\'`。 (2认同)

小智 8

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

可以在文本周围使用单引号,以防止外壳解释任何特殊字符。当用单引号引起来时,美元符号,空格,&符,星号和其他特殊字符都将被忽略。

$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.' 
Run Code Online (Sandbox Code Playgroud)

它将给出:

All sorts of things are ignored in single quotes, like $ & * ; |.
Run Code Online (Sandbox Code Playgroud)

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

双引号的行为与单引号类似,但双引号仍然允许外壳解释美元符号,反引号和反斜杠。众所周知,反斜杠会阻止单个特殊字符的解释。如果需要将美元符号用作文本而不是变量,则在双引号内很有用。它还允许转义双引号,因此不会将其解释为带引号的字符串的结尾。

$ echo "Here's how we can use single ' and double \" quotes within double quotes"
Run Code Online (Sandbox Code Playgroud)

它将给出:

Here's how we can use single ' and double " quotes within double quotes
Run Code Online (Sandbox Code Playgroud)

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

$ echo "The current Oracle SID is $ORACLE_SID"
Run Code Online (Sandbox Code Playgroud)

它将给出:

The current Oracle SID is test
Run Code Online (Sandbox Code Playgroud)

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

$ today=`date '+%A, %B %d, %Y'`
$ echo $today 
Run Code Online (Sandbox Code Playgroud)

它将给出:

Monday, September 28, 2015 
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案,因为明确指出“唯一不能放在单引号内的是单引号”。让我补充一下,反引号已被弃用,而 $() 与 POSIX 兼容,因此您应该更喜欢后者。 (3认同)

小智 5

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

' '用于任何事物时,没有进行“转换或翻译”。它按原样打印。

对于" ",无论它包围什么,都会被“翻译或转化”为其价值。

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

  • 在我看来,这是一个简短而简洁的答案,没有过于冗长,很容易让我理解。当说翻译/转换时,它们的意思是双引号将扩展变量,而单引号不会扩展变量。 (2认同)
  • 您所说的“转换或翻译”通常称为*插值。* 表达式“foo $bar baz”只是文字字符串“foo $bar baz”,而“foo $bar baz”则插值将变量“bar”放入文字符号“foo”和“baz”之间的字符串中,中间有空格。 (2认同)

Ini*_*ian 5

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

bash外壳支持两种方式做算术运算,一个定义的内置let命令和$((..))操作。前者计算算术表达式,而后者更像是复合语句。

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

使用时请参阅此示例 let

let 'foo = 2 + 1'
echo $foo
3
Run Code Online (Sandbox Code Playgroud)

在这里使用单引号绝对没问题,因为这里不需要变量扩展,请考虑以下情况

bar=1
let 'foo = $bar + 1'
Run Code Online (Sandbox Code Playgroud)

会失败,因为$bar下单引号不会扩展,需要双引号作为

let 'foo = '"$bar"' + 1'
Run Code Online (Sandbox Code Playgroud)

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

(( bar=1, foo = bar + 1 ))
Run Code Online (Sandbox Code Playgroud)

永远记住不要使用$((..))单引号

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

printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
Run Code Online (Sandbox Code Playgroud)

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

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

注意在内部使用了嵌套的双引号,没有它的文字字符串$((reqcnt++))被传递给requestCounter字段。

  • [Charles Duffy](/sf/users/988571/) [这里](/sf/ask/704708651/) 是一个很好的案例-a-shell-variable#comment71378550_10067297) 也用于双引号 `$((...))`。例如,这可能是“有点”偏执,不太可能有`IFS=0`,但这当然不是不可能的:) (2认同)