在while循环中丢失环境 [英] Losing environment in while loop

查看:48
本文介绍了在while循环中丢失环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个有趣的小玩笑预告片,我想解释一下.

A fun little bash teaser to which I'd love an explanation.

尽管我有两个循环构造是相同的,但显然不一样.似乎在进行 while 循环时,管道传输和重定向之间存在一些差异.

Two loop constructs I would have though are identical, clearly are not. Seems there's some difference in piping vs redirecting when doing a while loop.

输入文件

给出一个名为 values.txt 的示例文件,其中包含以下内容:

Given this sample file called values.txt with this content:

1
2
3
4
5
6

管道

$ value=0; cat values.txt | while read var; do value=`expr $value + $var`; done
$ echo $value
0

重定向到while

$ value=0; while read var; do value=`expr $value + $var`; done < values.txt
$ echo $value
21

为简单起见,很明显,在第一个版本中, while 循环的每个迭代都有效地作为()执行,而在第二个版本中,每个迭代均迭代为 {}

To be brief, clearly in the first version each iteration of the while loop executes effectively as () and in the second each iteration iterates as {}

问题不是() {} 之间的区别.我的问题是 while 循环在行为上有什么原因?

The question is not the difference between () and {}. My question is what causes this difference in behavior for while loops?

是出于逻辑原因,他们应该表现出不同的行为,还是只是出于兼容性原因而无法更改的早期错误选择?

Is there a logical reason they should behave differently or was it just a bad choice made early on that couldn't be changed for compatibility reasons? Is it ever possible to pipe to while and get {} behavior?

推荐答案

这是一个已知问题,并在此处进行了详细说明: http://mywiki.wooledge.org/BashFAQ/024

This is a known problem and is well explained here: http://mywiki.wooledge.org/BashFAQ/024

引用最具解释性的部分:

To quote the most explanatory part:

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

Different shells exhibit different behaviors in this situation:

  • BourneShell 在输入或输出任何东西时创建一个子shell(循环,大小写等),但是通过以下方式重定向了简单的命令:使用管道或重定向运算符('<','>').
  • BASH 仅在循环是管道的一部分时才创建新进程.
  • KornShell 仅当循环是管道的一部分时才创建它,但如果循环是管道的一部分则不创建它是它的最后一部分.
  • POSIX 指定bash行为,但扩展允许管道的任何或所有部分运行没有子外壳(因此也允许KornShell行为).
  • BourneShell creates a subshell when the input or output of anything (loops, case etc..) but a simple command is redirected, either by using a pipeline or by a redirection operator ('<', '>').
  • BASH creates a new process only if the loop is part of a pipeline.
  • KornShell creates it only if the loop is part of a pipeline, but not if the loop is the last part of it.
  • POSIX specifies the bash behaviour, but as an extension allows any or all of the parts of the pipeline to run without a subshell (thus permitting the KornShell behaviour, as well).

关于最后一个问题:是的,只有在bash> = 4.2的情况下,才能在某些shell中使用bash,并且在bash中也可以这样做,并且在代码之前先禁用工作控制并使用以下代码启用lastpipe选项:设置+ m;shopt -s lastpipe

As for the last question: yes, it is possible in certain shells, and in bash only if you have bash >=4.2, and preceed your code with disabling job control and enabling lastpipe option with the following code: set +m; shopt -s lastpipe

这篇关于在while循环中丢失环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆