为什么我不能在while循环中进行评估?

时间:2012-08-28 17:12:42

标签: bash shell

我想在循环中创建bash别名,循环从命令中读取行。为了逐行读取输出,我相信我需要将输出管道输入read。但是,当我这样做时,别名就不存在了。

如果我在.bashrc中包含以下内容:

for x in a1 a2; do
    eval "alias $x='echo foo'"
done

echo -e "a3\na4" | while read x; do
    eval "alias $x='echo foo'"
done

别名a1a2存在,但a3a4不存在。这两个循环之间有什么区别?

3 个答案:

答案 0 :(得分:6)

管道中的while循环在子shell中运行。你可以这样做:

while read x; do
    eval "alias $x='echo foo'"
done << EOF
a3
a4 
EOF

答案 1 :(得分:5)

问题在于管道。在a | b | c形式的管道中,每个单独的命令abc都在一个单独的子shell [ref]中运行,表示它接收到父执行环境(包括别名)的副本,并且它对自己的副本所做的任何更改(例如通过运行alias)都不会对父[{{ 3}}]。

在您的情况下,您可以通过编写:

来解决此问题
while read x; do
    eval "alias $x='echo foo'"
done < <(echo -e "a3\na4")

仍会在子shell中运行echo -e "a3\na4",但会在正常/父执行环境中运行while - 循环。

答案 2 :(得分:3)

在bash 4.2及更高版本中,您可以设置lastpipe选项以使管道的 last 命令不在子shell中执行。还必须关闭作业控制(set +m)才能使其生效。

shopt -s lastpipe
set +m
echo -e "a3\na4" | while read x; do
    alias $x='echo foo'
done