在 Bash 中,单引号 (''
) 和双引号 (""
) 有什么区别?
sh
、ash
、dash
、ksh
和 - 有一些警告 - zsh
)。
单引号不会插入任何内容,但双引号会。例如:变量、反引号、某些 \
转义等。
例子:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Bash 手册有这样的说法:
3.1.2.2 单引号 将字符括在单引号 (') 中会保留引号内每个字符的字面值。单引号之间不能出现单引号,即使前面有反斜杠。 3.1.2.3 双引号 将字符括在双引号 (") 中会保留引号内所有字符的字面值,但 $、`、\ 以及启用历史扩展时的 ! 除外。字符 $ 和 ` 保留它们在双引号中的特殊含义(请参阅 Shell 扩展)。反斜杠仅在后跟以下字符之一时才保留其特殊含义:$、`、"、\ 或换行符。在双引号内,删除后面跟有这些字符之一的反斜杠。没有特殊含义的字符前面的反斜杠保持不变。双引号可以用反斜杠在双引号中引用。如果启用,将执行历史扩展,除非 !出现在双引号中的使用反斜杠进行转义。 ! 前面的反斜杠没有被删除。特殊参数 * 和 @ 在双引号中时具有特殊含义(请参阅 Shell 参数扩展)。
accepted answer 很棒。我正在制作一个有助于快速理解该主题的表格。解释涉及一个简单的变量 a
以及一个索引数组 arr
。
如果我们设置
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" "" 被视为字面意思 inside '' 5 '\'' invalid can't escape a ' within '';使用 "'" 或 $'\'' (ANSI-C 引用) 6 "red$arocks" red $arocks 不扩展 $a;使用 ${a}rocks 保存 $a 7 "redapple$" redapple$ $ 后跟没有变量名 计算结果为 $ 8 '\"' \" \ 在 '' 9 "\'" \' \' 内没有特殊含义在 "" 内解释,但对 ' 10 "\"" " \" 在 "" 11 "*" 内解释 * glob 在 "" 或 '' 12 "\t\n" \t\n 内不起作用\t 和 \n 在 "" 或 '' 内没有特殊含义;使用 ANSI-C 引用 13 "`echo hi`" hi `` 和 $() 在 "" 内求值(反引号保留在实际输出中) 14 ' `echo hi`' `echo hi` `` 和 $() 不在 '' 内部求值(反引号保留在实际输出中) 15 '${arr[0]}' ${arr[0]} 无法访问数组inside '' 16 "${arr[0]}" apple array access works inside "" 17 $'$a\'' $a' 单引号可以在 ANSI-C quoting 18 "$'\t'" $ 内转义'\t' ANSI-C 引用不会在 "" 19 '!cmd' !cmd 历史扩展字符 '!' 内解释在 '' 20 "!cmd" cmd args 中被忽略 扩展为匹配 "cmd" 21 $'!cmd' 的最新命令 !cmd 历史扩展字符 '!'在 ANSI-C 引号内被忽略
也可以看看:
ANSI-C 引用 $'' - GNU Bash 手册
使用 $"" 进行语言环境翻译 - GNU Bash 手册
报价的三点公式
The special parameters * and @ have special meaning when in double quotes
那么 "*"
为什么会导致 *
?
"$@"
和 "$*"
是参数扩展。 "@"
和 "*"
不是。
event not found
错误消息。请参阅stackoverflow.com/questions/11816122/echo-fails-event-not-found
echo hi
被反引号包围。对不起,但我无法在评论中逃避反引号。
如果您指的是回显某些内容时会发生什么,那么单引号将逐字地回显它们之间的内容,而双引号将评估它们之间的变量并输出变量的值。
例如,这个
#!/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
其他人解释得很好,只想举个简单的例子。
可以在文本周围使用单引号,以防止 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
由于这是处理 bash
中的引号时的实际答案,因此在处理 shell 中的算术运算符时,我将在上面的答案中再补充一点。
bash
shell 支持两种算术运算方式,一种由内置 let
命令和 $((..))
运算符定义。前者评估算术表达式,而后者更多的是复合语句。
重要的是要理解与 let
一起使用的算术表达式会像任何其他 shell 命令一样经历分词、路径名扩展。因此,需要进行适当的引用和转义。
使用 let
时请参阅此示例
let 'foo = 2 + 1'
echo $foo
3
在这里使用单引号绝对没问题,因为这里不需要变量扩展,请考虑以下情况
bar=1
let 'foo = $bar + 1'
会惨败,因为单引号下的 $bar
将 not 扩展并且需要双引号作为
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
字段。
$[[...]]
语法,但也许你忘记它是对的。
' '
和 " "
的用法有明显的区别。
当 ' '
用于任何内容时,不会进行“转换或翻译”。它按原样打印。
对于 " "
,无论它包围什么,都被“转换或转换”为它的值。
通过翻译/转换,我的意思如下:单引号内的任何内容都不会被“翻译”为它们的值。它们将被视为在引号内。示例:a=23
,然后 echo '$a'
将在标准输出上生成 $a
。而 echo "$a"
将在标准输出上产生 23
。
'foo $bar baz'
只是文字字符串 foo $bar baz
而 "foo $bar baz"
将变量 bar
的值插入到之间的字符串中文字符号 foo
和 baz
之间有空格。
人们需要一个最小的答案,而不需要像我一样花费大量时间。
令人惊讶的是(对于那些正在寻找答案的人),以下是一个完整的命令:
$ echo '\'
其输出是:
\
甚至对于 bash 的长期用户来说,反斜杠在单引号内没有任何意义。也没有别的。
git_prompt
时,他们建议像这样使用它PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
,git prompt,根据这不应该工作。PS#
变量有什么特别之处吗?或者如果它不进行插值,为什么它会起作用。PS1
。试试echo $PS1
看看我的意思。但是PS1
在显示之前会进行评估(请参阅 bash 手册页中的PROMPTING
部分)。要对此进行测试,请尝试PS1='$X'
。您将没有提示。然后运行X=foo
,突然你的提示是“foo”(当 set 而不是 displayed 时已经评估了PS1
,你仍然没有提示)。$ name='O'Hara'
不合法,但$ name='O'\''Hara'
有效。即使单引号之间的单引号不合法,您也可以通过将每个'
替换为'\''
而没有空格来转义它。