关闭命令的一个标志和无限递归

关闭命令的一个标志和无限递归

由于在多个终端中使用时它会覆盖我的历史记录,因此我想关闭该功能fc -W。不幸的是我有经常打字的习惯。

我认为不可能创建别名,因为fc -W.

所以我尝试制作一个函数,如下所示:

# Make sure to never invoke fc -W
fc(){
    for x; do
        if [[ "${x}" == -W ]]; then
            echo "I'm sorry Dave. I'm afraid I can't do that."
            return
        fi
    done
    fc "${@}"
}

但是,现在调用fc "${@}"调用自身,并且我得到无限递归。通常我会通过使用 eg 来避免这种情况/usr/bin/fc,而不是fc, 但是:

$ type fc
> fc is a shell builtin

在这种情况下如何避免无限递归?或者是否有更好的方法来禁用命令的一个标志?

答案1

使用builtin

builtin fc "$@"

这将确保调用内置fc命令。


风格:诊断消息应发送到标准错误流,并且函数在失败时应返回非零状态:

echo 'Sorry, can not do that' >&2
return 1

答案2

您可以覆盖内置命令或外部命令或具有别名的函数。当别名执行时,同名的别名不会被扩展。因此,如果别名的扩展使用别名的名称,则会调用同名的内置或外部命令或函数。这意味着您可以以简单的方式使用别名将额外的选项传递给命令。但由于别名扩展的工作方式,您不能做更多的事情 - 它只是简单的单词替换,无需评估。

您可以使用函数覆盖内置命令或外部命令。当前正在执行某个名称的函数这一事实并不影响执行,特别是不影响函数名称的含义:它始终引用该函数。递归函数在 shell 编程中并不常见,但没有任何规则禁止它们。

command在 POSIX shell 中,您可以通过在调用之前放置一个名称来强制引用内置或外部命令。换句话说,command绕过别名和函数。在 zsh 中,command强制调用外部命令(除非posix_builtins设置了该选项),即它也绕过内置命令。要强制执行 zsh 中的内置函数,请使用builtin内置函数。

这导致了一种解决方案:在包装函数中,调用builtin fc而不是fc.

但是,这不一定是您的情况的最佳解决方案,因为您的函数将在任何地方被调用,包括fc来自其他函数的调用。当您覆盖内置行为时,我建议坚持使用别名。别名仅适用于您在命令行中键入或加载的内容.(又名source),不适用于加载的函数autoload -U(这是自动加载函数的推荐方法)。因此,定义一个调用fc您的包装函数的别名,并为您的包装函数指定一个不同的名称。

fc_wrapper () {
    for x; do
        if [[ "${x}" == -*W* ]]; then
            echo >&2 "I'm sorry Dave. I'm afraid I can't do that."
            return 1
        fi
    done
    \fc "${@}"
}
alias fc=fc_wrapper

我把\fc代替放在fc函数定义中。从别名定义之前加载定义时,这不是必需的.zshrc,但例如,如果您在交互式会话期间编辑或重新加载函数定义,则这是必需的。我还对该功能做了一些小的改进:

  • 打印标准错误的错误消息。
  • 如果您没有完成该工作,请返回错误状态。
  • 还抓获诸如此类的案件fc -WI。这并不完全可靠,因为它还会捕获诸如fc -R -- -W(从名为 的文件中读取历史记录)之类的调用-W,但对于此用例来说已经足够了。

相关内容