为了在我尝试shopt
在 Zsh 中使用而不是时提醒自己setopt
,我创建了以下别名,首先在 shell 提示符下对其进行测试:
$ alias shopt='echo "You\'re looking for setopt. This is Z shell, man, not Bash."'
尽管外部单引号匹配和内部双引号匹配,并且撇号被转义,但我被提示完成关闭引号:
dquote > _
这是怎么回事?
似乎转义被忽略了,或者由于多个解释级别而需要双重转义......所以,为了验证这个理论,我尝试了双重转义(以及三次转义,等等on) 一直到:
alias shopt='echo "You\\\\\\\\\\\\\\\\\\\\\\'re looking for setopt. This is Z shell, man, not Bash." '
并且从未见过任何不同的行为。这对我来说毫无意义。什么样的怪异巫毒会阻止外壳按我预期的方式运行?
实际的解决方案是不使用引号echo
,因为它实际上并不需要任何引号,并使用双引号alias
,并转义撇号,以便在编辑文本时将其忽略echo
。然后所有的实际问题都消失了。
你能帮助我吗?我需要解决这个令人困惑的问题。
这是
zsh
,伙计,不是fish
。在
zsh
中,就像在每个 Bourne-like shell(以及csh
)中一样,单引号是强引号,其中没有转义(除非使用@JdeBP 暗示的选项来rcquotes
模拟引号¹)。单引号字符串中不能有单引号,您需要首先关闭单引号字符串并使用另一种引用机制(如or )输入文字单引号:zsh
rc
\
"
或者:
虽然你也可以这样做:
(
"..."
是较弱的引号,其中几个字符,包括\
(这里用于转义嵌入的"
) 仍然是特殊的)。或者:
(
$'...'
是来自 ksh93 的另一种引用,'
可以用 进行转义\'
)。(顺便说一句,您也可以使用标准
set -o
代替setopt
inzsh
.bash
,由于历史原因,有两组选项,一组是您设置的,set -o
一组是用shopt
;zsh
像大多数其他外壳一样只有一组选项)。¹ 在
rc
Plan9 的 shell 中,也有类似 unix 的版本,单引号是唯一的引用机制(反斜杠和双引号是那里的普通字符),输入文字单引号的唯一方法是 with''
inside单引号,所以使用zsh -o rcquotes
,你可以这样做:这不是巫毒。这是正常的 POSIX shell 引用。 单引号字符串中没有转义机制。它们总是在下一个单引号处终止。有一个 Z shell 扩展,可以使两个连续的单引号字符串在它们之间放置一个单引号,您可以使用它。或者您可以终止单引号字符串,使用转义(或实际上是非单引号)单引号,然后开始第二个单引号字符串。
或者你不能在你的信息中使用缩写。☺
进一步阅读
其他答案很好地解释了为什么您会看到这种行为。但是,如果我可以就如何实际解决这个问题提出建议:
不要对任何复杂的东西使用别名。
当然,你可以绞尽脑汁想弄清楚如何嵌套 N 层引号,但对于别名来说,这很少值得。当别名足够复杂以至于它的引用变得不平凡时,只需切换到 shell 函数:
这将删除一整层引号,允许您稍后向 shell 函数添加更多代码,并且通常更易于阅读。它还允许对参数的插入方式和位置进行更精细的控制,而不是“只需替换行的开头,让剩余的单词放在可能的地方”的别名方法。例如,使用您的(更正后的)别名,如果您键入以下内容:
...然后你会得到这个输出:
这可能不是你想要的。shell 函数将使用您传递给它的任何参数,并默默地丢弃它们。
如果您不想与引号作斗争,请使用另一个字符,例如 Unicode U+2019,而不是
'
撇号。按住Ctrl+Shift并键入
u2019
,此字符将出现’
(呃...取决于您的语言环境?)。(U+2019) 的这种用法
’
是正确的,因为该字符正式用作撇号。Unicode 标准 10.0 版明确推荐这种用法。该标准承认'
(U+0027) 通常用作撇号,因为它存在于 ASCII 和键盘上,并且似乎允许这样做。但它随后指出’
(U+2019)更适合用作标点符号的撇号(并以缩略语为例)。唯一’
不推荐使用 (U+2019) 的撇号是那些用作变音符号而不是标点符号的撇号;这些写得最好ʼ
(U + 02BC)。来自标准第 6.2 节中的撇号(第 276 页):一条现已删除的评论给了我提示,让我得到了一半的答案。
在单引号字符串中转义单引号是不可能的。
双引号字符串中不存在此限制,因为我在最终解决方案中肯定会在双引号字符串中转义单引号: