Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.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
Bash 在while循环中丢失环境_Bash - Fatal编程技术网

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,这最终与
无关,而
循环是完美的答案。非常感谢。