根据我的理解,a \n应该解释为
"a\nb"
$'a\nb'
Run Code Online (Sandbox Code Playgroud)
但不在
'a\nb'
Run Code Online (Sandbox Code Playgroud)
但是,我看到以下内容:
(下面是我的zsh会话的字幕)
-0-1- ~ > zsh --version
zsh 5.1.1 (x86_64-unknown-cygwin)
-0-1- ~ > echo 'a\nb'
a
b
-0-1- ~ >
Run Code Online (Sandbox Code Playgroud)
zsh本身不解释\nin 'a\nb',但是内置解释echo。'a\nb'和"a\nb"是等价的,并且不包含换行符,而是(文字)字符序列\n。$'a\nb'另一方面,实际上确实包含换行符。
这里有两件事在起作用:
引用用于告诉外壳程序您想要一个字符本身,而不是外壳程序语法中可能具有的任何特殊含义。zsh有四种类型的引号,其中一些可以保留或增加一些字符或字符序列的特殊含义:
\:前面加单引号\。对于zsh说\n唯一手段“我想要的字符n”。由于n没有特殊含义,因此与just相同n。这会随着以下字符的变化而变化*:不加引号*用作通配符,以\*防止写入(例如:比较echo /*和的输出echo /\*)。如果你想通过文字\字面上看,你要引用它,例如与另一\:\\。'...':就像字面意义上的\任何字符枯萎一样'...',这包括其他引号方法。'foo* bar?'从本质上讲等同于foo\*\ bar\?(或者\f\o\o\*\ \b\a\r\?如果想要学究的话)。只有'它本身不能出现在带引号的字符串内,'...'因为它会标记qoute的结尾。(可以通过设置来更改RC_QUOTES。如果设置,则将一对单引号作为单引号:'foo''bar'?foo\'bar)"...":允许参数和命令替换。这意味着将a后面的单词$用作参数名称(例如"path: $PATH"),并将字符串包装$(...)或`...`用作命令替换(例如echo "Date: $(date)")。否则,它像'...'与允许的引用除外`,$,\和"用\。$'...':字符串insid $'...'被视为print内置的字符串参数。仅在这里,某些字母字符确实具有特殊的含义:\n换行符,\b退格键,\a铃铛字符等。\并且'可以分别用\\和引用\'。结果字符串被视为全引号。有没有参数或命令替换内部$'...'。echo:除了echo二进制或bash-builtin外echo,默认情况下zsh-builtin会识别(某些)转义序列,例如\n或\t。尽管通常需要使用/bin/echo或bash-builtin 来显式启用此行为(通常通过传递-e标志echo -e "foo\nbar":),但对于zsh-builtin则需要显式禁用它。通过传递-E标志(echo -E 'foo\nbar')或设置BSD_ECHO选项(setopt bsdecho),在这种情况下,-e标志可以像其他类型的一样用于重新启用功能echo。
这意味着'a\nb'和"a\nb"(以及a\\nb就此而言)都以a\nb(字面意义)传递,但是zsh-builtin echo然后解释\n,从而导致输出带有换行符的输出。另一方面$'a\nb',在传递给之前已经包含文字换行符echo。
跑步
for quoted_string in a\\nb 'a\nb' "a\nb" $'a\nb'; do
echo '>' $quoted_string '<'
/bin/echo -e '>' $quoted_string '<'
echo -E '>' $quoted_string '<'
/bin/echo '>' $quoted_string '<'
echo
done
Run Code Online (Sandbox Code Playgroud)
应该为您提供以下输出:
> a
b <
> a
b <
> a\nb <
> a\nb <
> a
b <
> a
b <
> a\nb <
> a\nb <
> a
b <
> a
b <
> a\nb <
> a\nb <
> a
b <
> a
b <
> a
b <
> a
b <
Run Code Online (Sandbox Code Playgroud)
如您所见,前三种引用之间没有区别,而第四种始终使用换行符打印。
顺便说一句:(perl至少是版本5;我不了解Perl 6)以您描述预期行为的方式表现。中的perl '...'行为与中的行为相同zsh。在另一方面"..."中perl行为像的组合"..."和$'...'的zsh:变量由像他们的价值和字符序列替换\n和\t被特殊处理。