好的,所以我正在尝试解析一个在列中输出我需要的行的文件,而且我无法使这个while
循环起作用,而且我真的很难过。
有趣的是,使用for
循环执行几乎完全相同的操作可以正常工作。有人可以解释一下这里发生了什么吗?
此...
e=""
for f in 1 2 3
do
echo $f
e="$e.$f"
done
echo $e
输出:
1
2
3
.1.2.3
但是这......
e=""
echo "1
2
3" | while read f
do
echo $f
e="$e.$f"
done
echo $e
输出:
1
2
3
显然,当$f
到达e="$e.$f"
时,两个循环在{{1}}中都有1,2或3个,那么第二个循环不起作用的是什么?
答案 0 :(得分:8)
我无法告诉你有多少次我不得不从某人的代码中删除这个错误。
管道基本上会生成分叉过程。 e在forked进程中设置,但是当它终止时(在wile循环结束时),父进程不知道e已经改变。简而言之,永远不要在涉及管道的命令中设置变量。管道完成后不会设置。更短......如果可以避免使用,请不要使用管道。
e=''
while read f
do
echo $f
e="$e.$f"
done << EOF
1
2
3
EOF
echo $e
答案 1 :(得分:3)
管道将在子shell中执行。所以在管道命令执行后,变量e没有改变。
答案 2 :(得分:3)
由于while read... done
是管道的一部分,它就像其他二进制文件(称为子shell )一样获得自己的分叉过程映像。 (令人困惑的部分是它是用shell编写的,但是它不是作为当前shell进程的一部分执行的。)这就是为什么变量不会得到更新。
作为一种解决方法,你总是可以做这样的事情(使用bashisms):
while read line
do
blablabla
done < <(echo "1 2 3")
在这里,您避免设置管道,因此while...done
shell代码将作为当前脚本的一部分执行。
答案 3 :(得分:1)
我猜这是变量范围的差异。将echo语句传递给while语句时,全局e不在其范围内,因此它打印f并设置新变量e。当while循环退出时,全局e没有改变。因此,您的陈述echo $e
不会打印任何内容。