为了在我尝试shopt
在 Zsh 中使用而不是时提醒自己setopt
,我创建了以下别名,首先在 shell 提示符下测试它:
$ alias shopt='echo "You\'re looking for setopt. This is Z shell, man, not Bash."'
尽管外部单引号匹配和内部双引号匹配,并且撇号被转义,但系统提示我用以下命令完成结束引号:
dquote > _
这是怎么回事?
看来转义被忽略了,或者由于多层解释而需要双重转义......所以,为了测试这个理论,我尝试了双重转义(以及三次转义,等等)上)一直到:
alias shopt='echo "You\\\\\\\\\\\\\\\\\\\\\\'re looking for setopt. This is Z shell, man, not Bash." '
和绝不看到任何不同的行为。这对我来说毫无意义。什么样的奇怪巫术阻止了 shell 的行为如我所料?
实际的解决方案是不使用引号echo
,因为它实际上不需要任何引号,并使用双引号alias
,并转义撇号,以便在echo
编辑文本时忽略撇号。然后所有的实际的问题就会消失。
你能帮助我吗?我需要解决这个令人困惑的问题。
答案1
这zsh
,伙计,不是fish
。
在 中zsh
,就像在每个类似 Bourne 的 shell 中一样(以及csh
),单引号是强引号,其中没有转义(除非使用rcquotes
以下选项@JdeBP 暗示其中zsh
模拟rc
引号 1)。单引号字符串中不能有单引号,您需要首先关闭单引号字符串并使用另一种引用机制(如\
或"
)输入文字单引号:
alias shopt='echo "You'\''re looking for setopt. This is Z shell, man, not Bash."'
或者:
alias shopt='echo "You'"'"'re looking for setopt. This is Z shell, man, not Bash."'
虽然你也可以这样做:
alias shopt="echo \"You're looking for setopt. This is Z shell, man, not Bash.\""
("..."
是较弱引号内的几个字符,包括\
(这里用于转义嵌入的"
)仍然是特殊的)。
或者:
alias shopt=$'echo "You\'re looking for setopt. This is Z shell, man, not Bash."'
($'...'
是 ksh93 的另一种引用,其中'
可以用 转义\'
)。
(顺便说一句,您还可以使用标准set -o
代替setopt
in zsh
. bash
,由于历史原因,它有两组选项,一组可以用 来设置set -o
;shopt
就像zsh
大多数其他 shell 一样,只有一组选项)。
1 在`rc`中,Plan9的shell,也有类似unix的版本,[单引号是唯一的引用机制](/a/296147)(反斜杠和双引号是那里的普通字符),唯一的方法要输入文字单引号,单引号内有“''”,因此使用“zsh -o rcquotes”,您可以这样做:
alias shopt='echo "您正在寻找 setopt。这是 Z shell,不是 Bash。"'
答案2
答案3
其他答案很好地解释了为什么您会看到这种行为。但如果我可以就如何实际解决这个问题提出建议:
即使是极其复杂的事情也不要使用别名。
相信你能试图弄清楚如何嵌套 N 层引号会绞尽脑汁,但为了别名而这样做是不值得的。当别名足够复杂以至于其引用变得不平凡时,只需切换到 shell 函数即可:
shopt(){
echo "You're looking for setopt. This is Z shell, man, not Bash."
}
这会删除整层引号,允许您稍后向 shell 函数添加更多代码,并且通常更容易阅读。它还允许更精细地控制参数的插入方式和位置,而不是“仅替换行的开头并让其余单词落在可能的位置”的别名方法。例如,对于您的(更正的)别名,如果您键入以下内容:
shopt -s some_opt
...然后你将得到这个输出:
You're looking for setopt. This is Z shell, man, not Bash. -s some_opt
这可能不是你想要的。 shell 函数将消耗您传递给它的任何参数,并默默地丢弃它们。
答案4
一条现已删除的评论给了我提示,让我找到了答案。
无法逃脱单引号在单引号字符串内。
双引号字符串中不存在此限制,因为我在最终解决方案中肯定会转义双引号字符串内的单引号:
alias shopt="echo You\'re looking for setopt. This is Z shell, man, not Bash."