进一步阅读

进一步阅读

为了在我尝试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代替setoptin zsh. bash,由于历史原因,它有两组选项,一组可以用 来设置set -oshopt就像zsh大多数其他 shell 一样,只有一组选项)。


1 在`rc`中,Plan9的shell,也有类似unix的版本,[单引号是唯一的引用机制](/a/296147)(反斜杠和双引号是那里的普通字符),唯一的方法要输入文字单引号,单引号内有“''”,因此使用“zsh -o rcquotes”,您可以这样做:
alias shopt='echo "您正在寻找 setopt。这是 Z shell,不是 Bash。"'

答案2

shopt='回声“你”

这不是巫术。这是正常的 POSIX shell 引用操作。 单引号字符串内没有转义机制。它们总是在下一个单引号处终止。有一个 Z shell 扩展,可以使两个连续的单引号字符串在它们之间放置一个单引号,您可以使用它。或者,您可以终止单引号字符串,使用转义(或实际上非单引号)单引号,然后开始第二个单引号字符串。

或者您不能在消息中使用缩写。 ☺

进一步阅读

  • “单引号”外壳命令语言。基本规格。 IEEE 1003.1:2017。公开组
  • “引用”外壳语法。 Z Shell 手册。

答案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."

相关内容