Bash:函数中的别名声明和行为

Bash: Alias declaration and behavoir in functions

经过反复试验,我发现如果在函数声明之后声明别名,则在函数中使用时无法识别别名。也许我弄错了,但是 bash 手册页似乎没有解决这种行为。举个例子:

#!/bin/bash
unalias -a
shopt -s expand_aliases

alias alias1=echo

function foo {
echo "Aliases in foo:"
alias
alias1 "Hello from foo!" #Succeeds
}

foo

function bar {
echo "Aliases in bar:"
alias
alias2 "Hello from bar!" #Fails
}

alias alias2=echo
bar

输出:

foo 中的别名:

别名 alias1='echo'

来自 foo 的问候!

栏中的别名:

别名 alias1='echo'

别名 alias2='echo'

./aliastest.sh:第 23 行:alias2:找不到命令

如本例所示,bar 中的 alias 命令确实包含 alias2=echo 但在调用时无法识别该命令。简而言之,我不明白 bash' 在这种情况下的行为。也许我没有正确理解关于这个问题的手册页?

来自 Bash 手册

Aliases are expanded when a command is read, not when it is executed.

这意味着您应该将别名放在函数之前。它的优点是您只需承担一次扩展成本,此后在每次函数调用时都不需要处理别名。

当Bash执行脚本时,它会按照读取的顺序执行语句。函数语句不执行函数,它定义函数(有点像变量赋值)。当它们被读取时,函数被保存在内存中,当它们在命令中被调用时,shell 不会返回到磁盘上的实际文件,而是会按照存储在内存中的方式执行它们,而不必担心扩展别名.

某个地方的某个人认为 re-doing 每次函数调用时的别名扩展是错误的、浪费的,或者可能太不可预测(在线更改别名可能会导致已经定义的函数实际发生变化),并决定反对它,更愿意在函数定义时执行别名扩展。

这也意味着如果一个函数被强制重新定义,例如通过再次获取脚本,任何新的别名都将被扩展。函数未冻结:它们可以是 "re-assigned",尽管函数的主要思想通常是能够重复调用它而不必重新定义它,因此您通常不会像使用变量或参数一样使用别名,从一个调用更改为下一个。

将函数声明放在脚本顶部,将实际调用放在脚本底部时,您可能会觉得这种做法很直观。请记住,别名对于函数就像函数对于命令一样:别名必须在声明的函数可用之前定义,就像在命令中引用函数之前必须声明函数一样。