Ale*_*lls 6 shell bash shell-script eval
使用有什么区别:
eval 'echo "foo"'
Run Code Online (Sandbox Code Playgroud)
和
echo 'echo "foo"' | bash
Run Code Online (Sandbox Code Playgroud)
有没有?
iga*_*gal 20
run by 的命令eval
在当前 shell 中执行,通过管道传输的命令bash
在 sub-shell 中执行,例如:
> echo 'x=42' | bash; echo $x
> eval 'x=42'; echo $x
42
Run Code Online (Sandbox Code Playgroud)
在评论中声称在bash
(>=4.2) 的更新版本中,第一个命令也可能具有相同的效果。然而,情况似乎并非如此。
实际上有几个因素会导致管道命令不在当前会话中运行:管道和bash
命令。
大多数情况下,管道命令在子 shell 中运行。Bash 手册(第 3.2.2 节:管道)有以下内容:
正如评论中所指出的,可以通过lastpipe
选项修改此行为。Bash 手册(第 4.3.2 节:The Shopt Builtin)对该lastpipe
选项有以下说明:
最后管
如果设置,并且作业控制未处于活动状态,shell 将运行当前 shell 环境中未在后台执行的管道的最后一个命令。
我们可以通过以下方式验证情况是否如此。
首先启用lastpipe
:
> shopt -s lastpipe
Run Code Online (Sandbox Code Playgroud)
然后禁用作业控制:
> set +m
Run Code Online (Sandbox Code Playgroud)
现在执行从管道内设置变量的命令:
> unset x
> echo x=42 | while IFS= read -r line; do eval "${line}"; done;
> echo $x
42
Run Code Online (Sandbox Code Playgroud)
请注意,我们使用while
循环和read
命令作为解决方法,因为该eval
命令无法从 stdin 读取其输入(因此无法从管道获取其输入)。
这个例子演示了管道中最右边的命令实际上可以在当前 shell 中执行。然而,这实际上并不影响我们原来的例子。即使lastpipe
启用和禁用作业控制,我们仍然会在管道到 时得到以下结果bash
:
> echo 'x=42' | bash; echo $x
>
Run Code Online (Sandbox Code Playgroud)
这是因为bash
命令本身在子 shell 中执行其输入。
归档时间: |
|
查看次数: |
2320 次 |
最近记录: |