带有和没有关键字的外壳功能定义



我花了我永远花了以下shell脚本不起作用的原因:

if command -v z > /dev/null 2>&1; then
    unalias z 2> /dev/null
    z() {
        [ $# -gt 0 ] && _z "$*" && return
            cd "$(_z -l 2>&1 |
                fzf --height 40% --nth 2.. --reverse --inline-info +s --tac 
                --query "${*##-* }" |
                sed 's/^[0-9,.]* *//')"
    }
fi

在这种情况下,函数定义需要函数关键字function z() {...}。没有它,我得到了:

~/.shell/functions:112: defining function based on alias `z'
~/.shell/functions:112: parse error near `()'

我找不到任何在函数定义中使用或不使用function关键字之间有任何区别的地方。为什么在这种情况下是解决方案?(我在ZSH和BASH中尝试)

来自bash参考手册:

别名在读取命令时,而不是执行命令时会扩展。

因此,当读取if语句时,

z不是执行时的。因此,即使您的unalias,别名也已经在您的if语句中扩展(即z() ...已扩展)。

添加 function的帮助是因为别名被扩展到时,它们被用作第一个单词。如果将function添加到您的函数声明中,则不会扩展任何内容。


检查此代码,该代码在复合命令中演示了别名的行为:

#!/usr/bin/env bash
shopt -s expand_aliases
alias greet='echo hello'
if true; then
    unalias greet 2> /dev/null
    #still outputs hello!
    greet  
    #not first word, outputs greet
    echo greet                                  
fi
#error!
greet

此片段表明别名foo在执行前确实会扩展。结果,有一个称为 bar的函数, foo

$ alias foo='bar'
$ foo() { echo hello; }
$ declare -f foo
$ declare -f bar
bar () 
{ 
    echo hello
}
#declaring with 'function' keyword will work as expected
$ function foo { echo hi; }
$ declare -f foo 
foo () 
{ 
    echo hi
} 

bash参考手册详细说明了别名的行为,并建议以下内容:

要安全,请始终将别名定义放在单独的行上,然后做 在复合命令中不使用别名。

man page(man bash)状态"保留单词函数是可选的。":

外壳功能定义 shell函数是一个称为简单命令的对象,并用新的位置参数执行复合命令。壳功能如下所示:

   name () compound-command [redirection]
   function name [()] compound-command [redirection]
          This  defines a function named name.  **The reserved word function is optional.**  If the function reserved word is supplied, the parentheses are optional.

最新更新