在 python 和 node.js 中,print 处理标量字符串的方式与处理集合的方式之间存在差异。
字符串被简单地打印为一个字符序列。结果输出通常是用户期望看到的,但它不能用作字符串在语言中的表示。但是当一个列表/数组被打印出来时,你得到的是一个有效的列表/数组字面量,可以在程序中使用。
例如在python中:
>>> print("x")
x
>>> print(["x"])
['x']
打印字符串时,您只看到字符。但是在打印包含字符串的列表时,python 添加了引号字符,因此输出是有效的列表文字。同样,如有必要,它会添加反斜杠:
>>> print("\\")
\
>>> print(["\\"])
['\\']
node.js 的工作方式完全相同:
$ node -p '"\\"'
\
$ node -p '["\\"]'
[ '\\' ]
当您打印包含单个反斜杠的字符串时,您只会得到一个反斜杠。但是当你打印一个包含一个由单个反斜杠组成的字符串的列表/数组时,你会得到一个带引号的字符串,其中反斜杠用反斜杠转义,允许它在程序中用作文字。
与在 node 和 python 中打印字符串一样,标准的echo shell 实用程序只打印字符串中的实际字符。在标准 shell 中,没有类似于 node 和 python 打印数组的机制。然而,Bash 确实提供了一种机制,可以以可以用作 bash 程序一部分的格式打印出变量的值:
$ quote=\"
# $quote is a single character:
$ echo "${#quote}"
1
# $quote prints out as a single quote, as you would expect
$ echo "$quote"
"
# If you needed a representation, use the 'declare' builtin:
$ declare -p quote
declare -- quote="\""
# You can also use the "%q" printf format (a bash extension)
$ printf "%q\n" "$quote"
\"
(参考:declare 和 printf 上的 bash 手册。或者在 bash 会话中键入 help declare 和 help printf。)
不过,这还不是全部。了解 shell 如何解释您键入的内容也很重要。换句话说,当你写
some_utility \" "\"" '\"'
some_utility 在 argv 数组中实际看到了什么?
在标准 shell(包括 bash)中的大多数上下文中,C 风格的转义序列(如 \t)不会被这样解释。 (标准 shell 实用程序 printf 会在这些序列出现在格式字符串中时解释这些序列,并且一些其他标准实用程序也解释这些序列,但 shell 本身不会。)标准 shell 对反斜杠的处理取决于上下文:
不带引号的字符串:反斜杠引用以下字符,无论它是什么(除非它是换行符,在这种情况下,反斜杠和换行符都从输入中删除)。
双引号字符串:反斜杠可用于转义字符 $、\、"、` ;此外,从输入中删除后跟换行符的反斜杠,就像在未引用的字符串中一样。在 bash 中,如果启用历史扩展(在 interactive shell 中默认情况下) , 也可以使用反斜杠来避免 ! 的历史扩展,但反斜杠保留在最后的字符串中。
单引号字符串:反斜杠被视为普通字符。 (因此,无法在单引号字符串中包含单引号。)
Bash 添加了另外两种引用机制:
C 风格的引用,$'...'。如果单引号字符串前面有一个美元符号,则字符串 中的 C 样式转义序列会以与 C 编译器大致相同的方式解释。这包括标准空白字符,例如换行符 (\n)、八进制、十六进制和 Unicode 转义符(\010、\x0a、\u000A、\U0000000A),以及一些非 C 序列,包括“控制”字符 (\cJ) 和 ESC 字符 \e 或 \E(与 \x1b 相同)。反斜杠也可用于转义 \、' 和 "。(请注意,这是一个与双精度反斜杠字符列表不同的列表- 带引号的字符串;这里,美元符号或反引号前的反斜杠不是特殊的,而单引号前的反斜杠是特殊的;此外,不解释反斜杠换行序列。)
特定于语言环境的翻译:$"..."。如果双引号字符串前面有美元符号,则反斜杠(以及变量扩展和命令替换)被解释为普通双引号字符串,然后在由当前语言环境确定的消息目录中查找该字符串。
(参考:Posix standard、Bash manual。)