请参阅下面的代码:
a()(alias x=echo\ hi;type x;alias;x);a
我在函数内部有一个别名,我不想更改外部环境(这就是为什么我使用()
而不是{}
),即使代码说别名已成功设置,它也不起作用,检查输出:
x is aliased to `echo hi'
...
alias x='echo hi'
x: command not found
我听说这样做shopt -s expand_aliases
可以解决,但不仅没有任何效果,而且我不能依赖,bash
因为我正在与dd-wrt
' busybox
s合作ash
。
有人知道这个问题吗?
答案1
我不使用dash
,但这是bash
手册中关于别名的说明:
有关别名的定义和使用的规则有些令人困惑。 在执行该行上的任何命令之前,Bash 总是至少读取一个完整的输入行。别名在读取命令时展开,而不是在执行命令时展开。因此,与另一个命令出现在同一行的别名定义在读取下一行输入之前不会生效。 该行上别名定义后面的命令不受新别名的影响。执行函数时,此行为也是一个问题。别名在读取函数定义时展开,而不是在执行函数时展开,因为函数定义本身就是复合命令。因此,函数中定义的别名只有在执行该函数之后才可用。为了安全起见,请始终将别名定义放在单独的行上,并且不要在复合命令中使用别名。
还有另一句话,这次来自zsh
手册:
下面的代码说明了一个常见的别名问题:
alias echobar='echo bar'; echobar
这会打印一条消息,指出
echobar
无法找到该命令。发生这种情况是因为读入代码时别名会扩展;一口气读完整行,这样当echobar
执行时就来不及扩展新定义的别名了。source
这通常是 shell 脚本、函数以及使用或执行的代码中的问题.
。因此,建议在非交互式代码中使用函数而不是别名。
我很确定其他 shell 中也有类似的情况。
答案2
如果您不反对使用eval
:
$ busybox ash -c 'a()(alias x=echo\ hi;type x;alias;eval x);a'
x is an alias for echo hi
x='echo hi'
hi
我不知道为什么这有效。