我想在循环中创建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
别名a1
和a2
存在,但a3
和a4
不存在。这两个循环之间有什么区别?
答案 0 :(得分:6)
管道中的while循环在子shell中运行。你可以这样做:
while read x; do
eval "alias $x='echo foo'"
done << EOF
a3
a4
EOF
答案 1 :(得分:5)
问题在于管道。在a | b | c
形式的管道中,每个单独的命令a
,b
和c
都在一个单独的子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