在while循环中丢失环境

时间:2012-09-16 06:48:14

标签: bash

一个有趣的小bash预告片,我喜欢这个解释。

我想要的两个循环结构是相同的,显然不是。似乎在进行while循环时管道与重定向有所不同。

输入文件

鉴于这个名为values.txt的示例文件包含以下内容:

1
2
3
4
5
6

管道

$ 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循环的每次迭代都有效地执行(),而在第二个循环中,每次迭代迭代为{}

问题不在于(){}之间的区别。我的问题是导致 while循环的行为差异

是否存在逻辑上的原因,他们应该采取不同的行为,或者只是因为兼容性原因而无法在早期做出错误的选择?是否有可能通过管道while并获得{}行为?

1 个答案:

答案 0 :(得分:7)

这是一个已知问题,这里有很好的解释: http://mywiki.wooledge.org/BashFAQ/024

引用最具说明性的部分:

  

在这种情况下,不同的炮弹表现出不同的行为:

     
      
  • BourneShell 在输入或输出任何内容时创建子shell   (循环,大小写等..)但是一个简单的命令被重定向,或者通过   使用管道或重定向操作符('&lt;','&gt;')。
  •   
  • BASH 仅在循环是管道的一部分时才创建新进程。
  •   
  • KornShell   仅当循环是管道的一部分时才创建它,但是如果循环则不是   是它的最后一部分。
  •   
  • POSIX 指定bash行为,但为   扩展允许管道的任何或所有部分运行   没有子shell(因此也允许KornShell行为)。
  •   

至于最后一个问题:是的,在某些shell中是可能的,只有在你有bash&gt; = 4.2的情况下才能使用bash,并且在你的代码前面有禁用作业控制并使用以下代码启用lastpipe选项:{{ 1}}