如何防止在 ZSH 中执行命令?
How to prevent execution of command in ZSH?
我为命令行编写了钩子:
# Transforms command 'ls?' to 'man ls'
function question_to_man() {
if [[ =~ '^\w+\?$' ]]; then
man ${2[0,-2]}
fi
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec question_to_man
但是当我这样做时:
> ls?
从 man
退出后我得到:
> zsh: no matches found: ls?
如何摆脱有关错误命令的消息?
?
是 zsh 特有的,是单个字符的通配符。这意味着如果您键入 ls?
zsh 会尝试在当前目录中查找匹配的文件名(任何以 "ls" 开头的三个字母的名称)。
有两种解决方法:
你可以制作“?” "unspecial" 通过引用它:ls\?
、'ls?'
或 "ls?"
.
你让 zsh 更好地处理不匹配的情况:
如果找不到匹配项,默认行为是打印错误。这可以通过禁用 NOMATCH
选项来改变(也不能设置 NULL_GLOB
):
setopt NO_NOMATCH
setopt NO_NULL_GLOB
如果没有匹配的文件,这将保持单词不变。
警告: 在(可能不太可能)存在具有匹配名称的文件的情况下,zsh 将尝试执行一个命令与第一个匹配文件的名称。也就是说,如果有一个名为 "lsx" 的文件,那么 ls?
将被 lsx
替换,zsh 将尝试 运行 它。这可能会也可能不会失败,但很可能不会达到预期的效果。
这两种方法各有利弊。 1. 可能不完全是您要找的东西,并且 2. 并非每次都能正常工作并改变您的 shell 行为。
另外(正如@chepner 在他的评论中指出的那样)preexec
运行s additionally to not 代替命令。这意味着你可能会得到 ls
的帮助,但 zsh 仍然会尝试 运行 ls?
甚至 lsx
(或其他匹配姓名)。
为了避免这种情况,我建议定义一个 command_not_found_handler
函数而不是 preexec
。来自 zsh manual:
If no external command is found but a function command_not_found_handler
exists the shell executes this function with all command line arguments. The function should return status zero if it successfully handled the command, or non-zero status if it failed. In the latter case the standard handling is applied: ‘command not found’ is printed to standard error and the shell exits with status 127. Note that the handler is executed in a subshell forked to execute an external command, hence changes to directories, shell parameters, etc. have no effect on the main shell.
所以这应该可以解决问题:
command_not_found_handler () {
if [[ =~ '\?$' ]]; then
man ${1%\?}
return 0
else
return 1
fi
}
如果您有很多匹配的文件名,但很少输错命令("Command not found" 错误的常见原因),您可能需要考虑改用它:
command_not_found_handler () {
man ${1%?}
}
这不检查“?”最后,只是删除最后一个字符(注意 ${1%?}
中缺少的“\”)并尝试 运行 man
其余的。因此,即使文件名匹配,man
也将是 运行,除非确实存在与匹配文件同名的命令。
注意: 这会干扰其他使用 command_not_found_handler
的工具,例如来自 Ubuntu 的 command-not-found
工具(如果为 zsh 启用) .
综上所述,zsh 有一个名为 run-help
的小部件,它可以绑定到一个键(在 Emacs 模式下,它默认绑定到 Alt+H) 而不是 运行s man
用于当前命令。
与上述相比,使用 run-help
的主要优点是:
- 您可以在键入较长命令时随时调用它,只要命令名称完整即可。
- 离开联机帮助页后,命令仍未更改,因此您可以继续在上面书写。
您甚至可以将其绑定到 Alt+? 以使其更相似:bindkey '^[?' run-help
我为命令行编写了钩子:
# Transforms command 'ls?' to 'man ls'
function question_to_man() {
if [[ =~ '^\w+\?$' ]]; then
man ${2[0,-2]}
fi
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec question_to_man
但是当我这样做时:
> ls?
从 man
退出后我得到:
> zsh: no matches found: ls?
如何摆脱有关错误命令的消息?
?
是 zsh 特有的,是单个字符的通配符。这意味着如果您键入 ls?
zsh 会尝试在当前目录中查找匹配的文件名(任何以 "ls" 开头的三个字母的名称)。
有两种解决方法:
你可以制作“?” "unspecial" 通过引用它:
ls\?
、'ls?'
或"ls?"
.你让 zsh 更好地处理不匹配的情况:
如果找不到匹配项,默认行为是打印错误。这可以通过禁用
NOMATCH
选项来改变(也不能设置NULL_GLOB
):setopt NO_NOMATCH setopt NO_NULL_GLOB
如果没有匹配的文件,这将保持单词不变。
警告: 在(可能不太可能)存在具有匹配名称的文件的情况下,zsh 将尝试执行一个命令与第一个匹配文件的名称。也就是说,如果有一个名为 "lsx" 的文件,那么
ls?
将被lsx
替换,zsh 将尝试 运行 它。这可能会也可能不会失败,但很可能不会达到预期的效果。
这两种方法各有利弊。 1. 可能不完全是您要找的东西,并且 2. 并非每次都能正常工作并改变您的 shell 行为。
另外(正如@chepner 在他的评论中指出的那样)preexec
运行s additionally to not 代替命令。这意味着你可能会得到 ls
的帮助,但 zsh 仍然会尝试 运行 ls?
甚至 lsx
(或其他匹配姓名)。
为了避免这种情况,我建议定义一个 command_not_found_handler
函数而不是 preexec
。来自 zsh manual:
If no external command is found but a function
command_not_found_handler
exists the shell executes this function with all command line arguments. The function should return status zero if it successfully handled the command, or non-zero status if it failed. In the latter case the standard handling is applied: ‘command not found’ is printed to standard error and the shell exits with status 127. Note that the handler is executed in a subshell forked to execute an external command, hence changes to directories, shell parameters, etc. have no effect on the main shell.
所以这应该可以解决问题:
command_not_found_handler () {
if [[ =~ '\?$' ]]; then
man ${1%\?}
return 0
else
return 1
fi
}
如果您有很多匹配的文件名,但很少输错命令("Command not found" 错误的常见原因),您可能需要考虑改用它:
command_not_found_handler () {
man ${1%?}
}
这不检查“?”最后,只是删除最后一个字符(注意 ${1%?}
中缺少的“\”)并尝试 运行 man
其余的。因此,即使文件名匹配,man
也将是 运行,除非确实存在与匹配文件同名的命令。
注意: 这会干扰其他使用 command_not_found_handler
的工具,例如来自 Ubuntu 的 command-not-found
工具(如果为 zsh 启用) .
综上所述,zsh 有一个名为 run-help
的小部件,它可以绑定到一个键(在 Emacs 模式下,它默认绑定到 Alt+H) 而不是 运行s man
用于当前命令。
与上述相比,使用 run-help
的主要优点是:
- 您可以在键入较长命令时随时调用它,只要命令名称完整即可。
- 离开联机帮助页后,命令仍未更改,因此您可以继续在上面书写。
您甚至可以将其绑定到 Alt+? 以使其更相似:bindkey '^[?' run-help