【问题标题】:Difference between single and double quotes in BashBash中单引号和双引号的区别
【发布时间】:2021-08-29 13:56:54
【问题描述】:

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

【问题讨论】:

标签: bash shell syntax quotes


【解决方案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 ${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 "" (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

另见:

【讨论】:

  • 接受的答案最后说The special parameters * and @ have special meaning when in double quotes那么"*"怎么会导致*?
  • @Karl-AnderoMere,因为在这种情况下它们根本没有作为参数展开。 "$@" 和 "$*" 是参数扩展。 "@" 和 "*" 不是。
  • @CharlesDuffy 谢谢,现在有意义了!
  • Csh 风格的历史引用可能最好关闭;它们不是很有用,关闭它们可以帮助您避免讨厌的event not found 不带引号的感叹号错误消息。见stackoverflow.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 的长期用户来说,反斜杠在单引号内没有任何意义。其他也没有。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        相关资源
        最近更新 更多