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

时间:2011-07-14 17:55:27

标签: bash shell syntax quotes

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

6 个答案:

答案 0 :(得分:447)

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

示例:

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

Bash手册有这样说:

  

3.1.2.2 Single Quotes

     

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

     

3.1.2.3 Double Quotes

     

用双引号括起字符(")会保留引号中所有字符的字面值,但$`\除外,启用历史记录扩展时,!。字符$`在双引号中保留其特殊含义(请参阅Shell Expansions)。只有在后跟以下字符之一时,反斜杠才会保留其特殊含义:$`"\或换行符。在双引号内,将删除后跟其中一个字符的反斜杠。没有特殊含义的字符前面的反斜杠不做修改。双引号可以在双引号内引用,前面加一个反斜杠。如果启用,则将执行历史记录扩展,除非使用反斜杠转义出现在双引号中的!。 <{1}}之前的反斜杠不会被删除。

     

特殊参数!*在双引号中具有特殊含义(请参阅Shell Parameter Expansion)。

答案 1 :(得分:207)

如果你指的是当你回应某些东西时会发生什么,单引号就会回显你在它们之间的内容,而双引号将评估它们之间的变量并输出变量的值。

例如,这个

#!/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

答案 2 :(得分:181)

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 ${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
---+-------------+-------------+--------------------------------------------------------------------

另见:

答案 3 :(得分:5)

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

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

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

它将给出以下内容:

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

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

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

$ 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 

答案 4 :(得分:1)

由于这是处理bash中的引号时的实际答案,因此在处理Shell中的算术运算符时,我将在上面的答案中再加上一个要点。

bash外壳程序支持两种算术运算方法,一种是通过内置的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字段。

答案 5 :(得分:0)

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

在任何事物上使用' '时,都不会进行“转换或翻译”。它按原样打印。

使用" ",无论包围什么,都将“转换或转换”为其值。

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