在"和读取-r线之间的bash是否有任何区别;做......;完成< file`和`cat file |而IFS =读-r线;做......; done`?

时间:2014-10-20 17:39:36

标签: bash

我正在学习bash,我在互联网上发现了一个教程,说明这些是相同的:

while read -r line;
do
    ...
done < file

$ cat file | while IFS= read -r line;
do
    ...
done

这两个循环中是否有任何微妙的差异,它们是否真的相同?

2 个答案:

答案 0 :(得分:8)

最大的区别在于,在管道中,while循环在子shell中执行,因此如果更改while正文中任何变量的值,那么这些变量将在管道完成。

$ foo=5
$ cat file | while IFS= read -r line; do
>    foo=$line  # assume $line is not 5
> done
$ echo $foo
5
$ while IFS= read -r line; do
>  foo=$line
> done < file  # Assume one line with the word foo
$ echo $foo
foo

bash 4.2中,可以使用lastpipe选项来缓解这种情况,该选项允许管道中的最后一个命令在当前shell而不是子shell中执行。

除此之外,使用输入重定向的版本更有效,因为它不需要启动额外的进程。

答案 1 :(得分:1)

除了chepner关于子壳的观察之外,其中一个循环使用IFS=而一个循环使用read

IFS=使用此变量来分割单词。使用一个变量,这会影响前导和尾随空格。

使用$ IFS= read -r line <<< " test " $ printf "<%s>\n" "$line" < test > ,它会被保留:

$ read -r line <<< "   test   "
$ printf "<%s>\n" "$line"
<test>

否则,它被剥离了:

IFS=

你可以想象第一个非{{1}}循环会破坏多少破坏,例如一个Python文件。