一个有趣的小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
并获得{}
行为?
答案 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}}