Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个For循环与Bash中的While循环不同?_Bash_Variables_Loops - Fatal编程技术网

为什么这个For循环与Bash中的While循环不同?

为什么这个For循环与Bash中的While循环不同?,bash,variables,loops,Bash,Variables,Loops,好的,我正试图解析一个文件,它在列中输出我在行中所需要的内容,但我无法在循环工作时得到这个,我真的被难倒了 有趣的是,使用for循环执行几乎完全相同的操作确实有效。有人能解释一下这是怎么回事吗 这个 e="" for f in 1 2 3 do echo $f e="$e.$f" done echo $e 产出: 1 2 3 .1.2.3 1 2 3 但是这个 e="" echo "1 2 3" | while read f do echo $f e

好的,我正试图解析一个文件,它在列中输出我在行中所需要的内容,但我无法在循环工作时得到这个
,我真的被难倒了

有趣的是,使用
for
循环执行几乎完全相同的操作确实有效。有人能解释一下这是怎么回事吗

这个

e=""
for f in 1 2 3
do 
    echo $f 
    e="$e.$f"
done
echo $e
产出:

1
2
3
.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
.1.2.3
1
2
3

显然,当它们到达
e=“$e.$f”
时,这两个循环在
$f
中都有1、2或3,那么第二个循环不起作用究竟是怎么回事呢?

我猜这是变量范围的不同。当您将echo语句导入while语句时,全局e不在其范围内,因此它打印f并设置一个新变量e。当while循环退出时,全局e没有改变。因此,您的语句
echo$e
不会打印任何内容。

管道将在子shell中执行。因此,在管道命令执行之后,变量e没有改变。

我无法告诉您我有多少次不得不从某人的代码中删除这个bug

基本上,管道生成一个分叉过程。在分叉进程中设置了e,但是当它终止时(在wile循环的末尾),父进程不知道e已经改变了。简而言之,切勿在涉及管道的命令中设置变量。管道完工后,将不会设置它。更短的如果可以避免,不要使用管道

e=''
while read f
do
  echo $f
  e="$e.$f"
done << EOF
1
2
3
EOF
echo $e
e=''
读f时
做
回声$f
e=“$e.$f”

在读取时作为
完成。。。done
是管道的一部分,它像其他二进制文件一样获得自己的分叉进程映像(称为子shell)。(令人困惑的是它是在shell中编写的,但是它并不是作为当前shell进程的一部分执行的。)这就是为什么变量不会得到更新

作为一种变通方法,您始终可以这样做(使用bashisms):

读取行时
做
喋喋不休

管道是否有自己的局部范围?你有点像echo是一个分叉过程,什么也不返回。它是一个子进程,并获得一个新的作用域。如果您可以将e作为命令的引用传递,它将更新全局可访问的e。太棒了,谢谢!我的第二个问题将是“我如何修复它?”+1,因为它向我展示了一种新的符号。我从未见过称为进程替换的
,它不是非常可移植(但可以通过创建临时文件来模拟)是的,即使在while循环中导出,也不能将var“推”到父shell。