奇怪的bash别名扩展

fri*_*ann 2 bash recursion alias

我有一堆函数和一些别名.我从未想到的是这两个问题:

export EDITOR="emacsclient -t"
alias vi='$EDITOR'
alias pa='ps ax | egrep -i '
Run Code Online (Sandbox Code Playgroud)

当我进入

pa vi
Run Code Online (Sandbox Code Playgroud)

我明白了

egrep: invalid option -- 't'
Run Code Online (Sandbox Code Playgroud)

显然,"vi"在另一个别名内部扩展,即使它不在行的开头.为什么这样,我能做些什么呢?

要仔细检查,这个:

ps ax | egrep vi
Run Code Online (Sandbox Code Playgroud)

正确执行.bash --version GNU bash,版本4.3.11(1)-release(x86_64-pc-linux-gnu)

ric*_*ici 8

你偶然发现了一个鲜为人知的shell编程陷阱.

通常,vi在该上下文中不会进行别名扩展,因为alias扩展仅适用于命令中的第一个单词(环境变量赋值除外).但是,正如bash手册所示:

如果别名值的最后一个字符为空,则还会检查别名后面的下一个命令字的别名扩展.

单词不能跨越别名及其周围的文本,因此不需要最后的空格:

alias pa='ps ax | egrep -i '
Run Code Online (Sandbox Code Playgroud)

如果您将其更改为:

alias pa='ps ax | egrep -i'
Run Code Online (Sandbox Code Playgroud)

事情将按预期发挥作用.但是你应该使用shell函数而不是别名; 功能更强大,更不古怪,同样快.

注意:对于那些寻找更多证据表明bash是错误的人,我必须补充一点,以空白结尾的别名的特殊行为来自Posix规范,因此在任何一致的shell上都是相同的:

如果替换单词的别名的值以a结尾<blank>,则shell应检查下一个命令字是否有别名替换; 此过程将继续,直到找到一个不是有效别名或别名值不以a结尾的单词<blank>.(XSH,§2.3.1)