Bash 在while循环中丢失环境
这是一个有趣的小游戏,我想解释一下 虽然我有两个循环结构是相同的,但显然不是。在执行Bash 在while循环中丢失环境,bash,Bash,这是一个有趣的小游戏,我想解释一下 虽然我有两个循环结构是相同的,但显然不是。在执行while循环时,管道与重定向似乎有些不同 输入文件 给定名为values.txt的示例文件,其中包含以下内容: 1 2 3 4 5 6 管道至while $ value=0; cat values.txt | while read var; do value=`expr $value + $var`; done $ echo $value 0 $ value=0; while read var; do va
while
循环时,管道与重定向似乎有些不同
输入文件
给定名为values.txt
的示例文件,其中包含以下内容:
1
2
3
4
5
6
管道至while
$ value=0; cat values.txt | while read var; do value=`expr $value + $var`; done
$ echo $value
0
$ value=0; while read var; do value=`expr $value + $var`; done < values.txt
$ echo $value
21
重定向到while
$ value=0; cat values.txt | while read var; do value=`expr $value + $var`; done
$ echo $value
0
$ value=0; while read var; do value=`expr $value + $var`; done < values.txt
$ echo $value
21
$value=0;读var时;do value=`expr$value+$var`;done
简而言之,在第一个版本中,while
循环的每个迭代都作为()
有效地执行,在第二个版本中,每个迭代都作为{}
进行迭代
问题不是()
和{}
之间的区别。我的问题是,是什么导致了while
循环的这种行为差异
是否有一个逻辑上的原因,他们应该采取不同的行为,或者只是一个错误的选择,不能改变早期的兼容性的原因?是否有可能在时通过管道连接到
,并获得{}
行为?这是一个已知的问题,在这里有很好的解释:
引用最具说明性的部分:
在这种情况下,不同的壳表现出不同的行为:
- BourneShell在输入或输出任何内容时创建子shell
(循环、大小写等)但是一个简单的命令被重定向,或者
使用管道或重定向运算符(“”)李>
- BASH仅当循环是管道的一部分时才创建新流程李>
- KornShell
仅当循环是管道的一部分时创建它,但如果循环
这是它的最后一部分李>
- POSIX指定bash行为,但作为
扩展允许管道的任何或所有部分运行
没有子shell(因此也允许KornShell行为)
至于最后一个问题:是的,这在某些shell中是可能的,并且只有在bash>=4.2,并且在代码前面禁用作业控制并使用以下代码启用lastpipe选项时,在bash中才可能:set+m;shopt-s lastpipe
在第一个版本中,while部分在子shell中启动(因为管道)。因此,$value不会改变。在第二部分中,while在当前shell中运行,并且修改了$value。在子shell中添加导出以查看差异。谢谢,@Gregor,但是shell{}
和子shell()
之间的差异不是问题所在。问题是为什么一个是外壳,一个是子外壳。我同时发现了一些关于子外壳和管道的材料。还没有得到完整的答案。区别不在于而在于;这并不是一个糟糕的选择——使用管道启动子流程,不管您将它管道到什么地方,否则它将无法工作。基本上,您回答自己:不,如果每次都不导出所有内容,您就不能做您想做的事情,而且您不需要这样做,因为您有一个解决方案already@moopet管道本身创建了子shell,这最终与无关,而循环是完美的答案。非常感谢。