命令替换中的别名应该如何表现?

命令替换中的别名应该如何表现?

我用不同的 shell 测试了几个脚本,结果有所不同。

# test 1
foo(){ echo $(al);}
alias al='echo 123'
foo

# test 2
alias al='echo 123'
foo(){ echo $(al);}
alias al='echo abc'
foo

# test 3
alias foo='echo $('
echo $(foo echo '123'))

# test 4
alias foo='echo $('
echo "$(foo echo '123'))"

# test 5
alias bar='echo 123)'
echo $(bar
bash 5.1.16(使用 --posix) 昆山2020.0.0 zsh 5.9 破折号 0.5.12 亚什 2.53
测试1 123 123 123 阿尔:未找到 没有这样的命令al
测试2 ABC ABC ABC 123 123
测试3 意外的标记) )意外 123 123 123
测试4 123 123 123 123 123
测试5 意外的文件结束符 (无与伦比的 未找到命令:barecho 123 123

所以基本上 bash 和 ksh 进行惰性别名替换,而 dash 和 yash 进行急切别名替换。 zsh 的行为有点难以解释,特别是在情况 5 中,当它尝试查找 command 时barecho

测试 4 是所有 shell 都同意的唯一情况。这很令人困惑,因为POSIX标准 2.2.3 双引号说:

带引号的字符串中也包含在“$(”和匹配的“)”之间的输入字符不应受到双引号的影响,而是应定义其输出替换“$(...)”的命令当单词扩展时。令牌识别中的令牌化规则(不包括别名替换中的别名替换)应递归应用以查找匹配的“)”。

该标准规定,当尝试在双引号内的命令替换中查找匹配的括号时,shell 不应采用别名替换。但所有 shell 都在双引号内使用别名替换,而有些 shell 如果没有双引号则不会。

问题是:某些 shell 在某些情况下是错误的,还是它们只是不同?即是否有一些规则说明在这种情况下正确的行为应该是什么?

相关内容