6

我想在循环中从命令读取行的循环中创建 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存在,但a3又不a4存在。这两个循环有什么区别?

4

3 回答 3

6

管道中的 while 循环在子外壳中运行。你可以做:

while read x; do
    eval "alias $x='echo foo'"
done << EOF
a3
a4 
EOF
于 2012-08-28T17:15:12.447 回答
5

问题是管道。在表单的管道中a | b | c,每个单独的命令abc都在单独的子shell [ ref ] 中运行,这意味着它接收到父执行环境的副本(包括别名),以及它对其自身所做的任何更改复制(例如通过运行alias)对父级 [ ref ] 没有影响。

在您的情况下,您可以通过以下方式解决此问题:

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

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

于 2012-08-28T17:14:22.620 回答
3

In bash 4.2 and later, you can set the lastpipe option to keep the last command of a pipe from executing in a subshell. Job control must also be off (set +m) for this to work.

shopt -s lastpipe
set +m
echo -e "a3\na4" | while read x; do
    alias $x='echo foo'
done
于 2012-08-28T17:28:20.707 回答