命令行 Zsh 中的注释

179

在 Ubuntu 上我从 Bash 切换到了 Zsh,感觉很不错。但是有一件事情我非常想要实现却找不到方法。

在 Bash 中,当我输入一个长命令时发现需要先运行其他命令,我只需要像下面这样将它注释掉:

me@home> #mysuperlongcommand with some arguments
me@home> thecommandIhavetorunfirst #and then: up up
me@home> #mysuperlongcommand with some arguments #I just need to uncomment it!
然而,与zsh不同的是,这种经常出现的情况并不容易解决,因为#mysuperlongcommand将被直接运行(导致:zsh: command not found: #mysuperlongcommand)。

这也很危险,因为如果您在注释中放置一个;字符,它将执行后续的命令(我刚刚运行了一个我还没有计划运行的rm -r操作:P)。 - Moshe Jonathan Gordon Radian
6个回答

251

最近开始尝试使用zsh时,我也遇到了这个问题。您可以在您的.zshrc文件中执行setopt interactivecomments(以使其永久生效),来激活类似于bash的注释。

Z Shell Manual指出,虽然这是Korn shell和Bourne shell(也猜想为Bourne-again shell)的默认行为,但对于Z shell而言,则不是默认行为:

在下列列表中,所有仿真环境中默认设置的选项都被标记为<D>;仅在csh、ksh、sh或zsh仿真环境中默认设置的选项则分别标记为<C><K><S><Z>

交互式注释 (-k) <K> <S> 即使在交互式 shell 中也允许注释。

6
如果只是偶尔需要,您也可以使用 set -k。但我建议将这个答案中的 setopt 行添加到您的 zshrc 文件中。 - Hamish Downer
43
这不是默认行为的原因是什么? - naught101
4
@naught101 提到,zsh 的许多最佳功能默认关闭。不知道为什么。 - zzapper
1
@naught101 我也喜欢,尽管有些工具不喜欢;) - aryndin
1
我曾经做过这件事,但是设置似乎不是永久的,稍后就会消失。也许如果我将其添加到.zshrc中,它就会起作用。 - Caleb Stanford
显示剩余3条评论

47

我使用

bindkey "^Q" push-input

从zsh手册中得知:

将整个多行结构推入缓冲区栈并返回顶级(PS1)提示符。如果当前解析器结构只有一行,则这与push-line完全相同。下次编辑器启动或使用get-line弹出时,该结构将从缓冲区栈顶部弹出并加载到编辑缓冲区中。

因此看起来是这样的:

> long command
Ctrl+Q => long command disappears to the stack
> forgotten command
long command reappears from stack
> long command
另外,如果你设置了INTERACTIVE_COMMENTS选项(setopt INTERACTIVE_COMMENTS),你就可以在交互式shell中像平时一样使用注释。

2
@Mihnea 如果命令消失了,那么 push-input 应该是在工作。当您运行下一个命令或只需按 Enter 时,它应该会重新出现。它不会这样做吗? - Michał Politowski
有没有办法与子进程共享堆栈?当我忘记启动屏幕时,我经常在bash中使用注释功能,例如:'#large command; history -a; screen',然后从历史记录中在屏幕内捡起来... - barbaz
1
@barbaz 可以使用 read -zprint -z 操作堆栈,因此通过一些脚本和临时文件可以实现。但是,编写一个自定义的 zle 小部件来将命令行保存到临时文件可能更简单,共享历史记录也会更简单。 - Michał Politowski
1
虽然当前被接受的答案回答了提问者的“问题”,但是这个答案回答了提问者的“意图”。也就是说,zsh有更好的方法来实现预期的结果,而这就是它。 - wjv
1
这应该是被接受的答案。如果你使用 oh-my-zsh,你可以直接使用 Ctrl-Q。 - Gecko
显示剩余3条评论

22

我也经常这样做。我的做法是剪切长命令,执行需要先执行的命令,然后再将长命令粘贴回来。这很简单: CTRL+U 可以将当前命令剪切到缓冲区,CTRL+Y 可以将其粘贴。在 zsh 和 bash 中都适用。


嗯,实际上,我的方法是一个解决办法,而你的方案是最佳选择 ;) - fbiville
4
这不应该成为被采纳的答案。下面的解决方案建议使用“setopt interactivecomments”。原因是,如果你只是删除当前命令,那么它就不会出现在你的zsh历史记录中;此外,在键入新命令时,如果想要使用剪切和粘贴操作而不覆盖你正在尝试保存的命令,则也很难进行。 - Douglas
1
使用注释和这个答案中的解决方案都是解决方法;Michał Politowski发布的推送输入方法更加正确。 - Fredrik

11
将行setopt INTERACTIVE_COMMENTS添加到您的~/.zshrc文件中,保存并重新启动shell。
这是对@Lajnold和@Hamish Downer的评论的澄清。我花了一点时间才弄清楚如何使这个更改永久化。您可能想在导出变量之前添加该行,因此可以在文件顶部添加它。我已经在我的~/.zshrc文件中添加了setopt PROMPT_SUBST,所以我只是在那一行之后添加了它。这将确保每次启动zsh终端时都加载设置。

set interactive_comments 对于命令行也适用。我想知道为什么这对函数内的注释不起作用? - Geoff Langenderfer
我的翻新版Mac Mini自带Catalina,但在我的主目录中甚至没有.zshrc文件。谢谢。 - Love and peace - Joe Codeswell
1
一旦您编辑了~/.zshrc文件,您可以通过运行以下命令将更改应用到当前的shell环境中,而无需关闭或重新启动任何内容:source ~/.zshrc - Kaan

5
: sh generate_sample.sh arg1

在zsh中,添加":"不会执行该命令。
sh generate_sample.sh : arg1

现在的arg1已被注释。

我正在使用Mac OS Big Sur,并且已经多次使用过它。

编辑:如果没有空格,“:”命令会起作用。 “:command”是正确的,但“: command”不正确。


这似乎可行?但是我很难通过谷歌搜索找到更多信息... - Daniel Waltrip
@DanielWaltrip 请查看 https://dev59.com/unA75IYBdhLWcg3wkZ6A 以获取有关bash的详细信息,但同样适用于zsh。 - Michael Sorens

0
除了由@Lajnold提出的setopt interactivecomments建议之外,你可能还想添加以下内容,以防止某些注释被写入历史记录(来自https://superuser.com/questions/352788/how-to-prevent-a-command-in-the-zshell-from-being-saved-into-history):
这将覆盖ZSH内置函数zshaddhistory():
  • 将记录以第1列开始且后面没有一个或多个空格的注释(即#我想回头再看的某个命令)
  • 不会记录以第1列开始且后面有一个或多个空格的注释
  • 不会记录以空格从第1列开始缩进的注释
  • 不会记录在第1列有空格的命令(方便的快捷方式,用于运行不希望被记录的命令)
setopt interactivecomments

function zshaddhistory() {
  emulate -L zsh
  if ! [[ "$1" =~ "(^#\s+|^\s+#|^ )" ]] ; then
      print -sr -- "${1%%$'\n'}"
      fc -p
  else
      return 1
  fi
}

供参考,这是默认的zshaddhistory()http://zsh.sourceforge.net/Doc/Release/Functions.html

zshaddhistory() {
  print -sr -- ${1%%$'\n'}
  fc -p .zsh_local_history
}

或者只需按照链接中提到的在您的~/.zshrc中添加 setopt HIST_IGNORE_SPACE - Scott Centoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接