我正在学习bash,我在互联网上发现了一个教程,说明这些是相同的:
while read -r line;
do
...
done < file
$ cat file | while IFS= read -r line;
do
...
done
这两个循环中是否有任何微妙的差异,它们是否真的相同?
答案 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文件。