Ole*_*nge 4 bash alias newlines
在 Bash 中,我运行:
alias myalias='echo foo
echo bar
echo baz'
myalias
Run Code Online (Sandbox Code Playgroud)
返回:
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)
但:
ssh localhost "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias"
Run Code Online (Sandbox Code Playgroud)
返回:
foo
Run Code Online (Sandbox Code Playgroud)
为什么?
我想你发现了 Bash 的一个错误。此错误特定于 option -c
。
远程运行与你的多行别名问题无关。您可以在本地 bash 中尝试。但不是在 bash 脚本或交互式 bash 中,请尝试使用-c
选项,如下所示
bash -c "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias"
Run Code Online (Sandbox Code Playgroud)
与您的问题相同的输出。仅foo
打印。
要获得正确的(预期的)输出,您必须至少在 之后再添加一行myalias
,正如@cuonglm 建议的那样。
bash -c "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias
:"
Run Code Online (Sandbox Code Playgroud)
为什么会这样?为什么myalias
帮助后多一行?
我只想说这没有意义。Bash 中没有任何文档解释或提到这种情况,一点也不。它不应该以这种方式运行。这是一个错误。阅读代码后,您将确定这一点。
回到第一个有问题的命令。这次不要改变任何东西,只需用 "ONESHOT" undefined重新编译 bash ,然后你就会得到正确的(预期的)输出。是的,你没听错,因为不同的编译时配置,该命令有两种不同的行为。
定义ONESHOT
与否会导致在 Bash 代码中为-c "command"
. 如果undefine ONESHOT,-c "command"
将运行正常的代码路由,这是几乎所有bash执行的代码路由,例如交互命令和bash脚本。但是如果定义了ONESHOT,-c "command"
就会运行另一条专门为它设计的特定路由,通过避免fork来提高它的性能。
对于这种情况,正常且最常用的方式可以给出正确的输出,而特定方式则不能。我认为不一致的行为不是 Bash 作者想要的。至于哪种行为是对的,我倾向于认为正常的方式是对的。
以下代码段与该错误有关。它来自文件 builtins/evalstring.c 中的函数 parse_and_execute()
while (*(bash_input.location.string))
{
...
}
Run Code Online (Sandbox Code Playgroud)
此while
循环将按行运行,在一个循环中处理一行。在 read 之后myalias
,命令中的最后一行(见上文),条件 inwhile
将变为假。myalias
扩展为三行回声,但在这个循环中只处理了一个回声;另外两个回声将在下一个循环中处理,但是......没有另一个循环。
如果myalias
在 read之后再添加一行myalias
,则条件 inwhile
将保持为真,因此另外两个 echo 将有机会在下一个循环中运行。最后一行 aftermyalias
将在处理完所有扩展的回声后myalias
处理。
更新
忘记说这个问题涉及的Bash版本了,就是
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
891 次 |
最近记录: |