我正在学习bash,发现网上有一篇教程说这两个命令是相同的:
while read -r line;
do
...
done < file
$ cat file | while IFS= read -r line;
do
...
done
这两个循环有微小的差异还是完全相同?
我正在学习bash,发现网上有一篇教程说这两个命令是相同的:
while read -r line;
do
...
done < file
$ cat file | while IFS= read -r line;
do
...
done
最大的区别在于,在pipeline中,while
循环在子shell中执行,因此如果您在while
主体中更改任何变量的值,那么这些更改将在pipeline完成后丢失。
$ 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
IFS=
,而另一个则没有。
read
使用该变量来分割单词。对于一个变量,这会影响前导和尾随空格。IFS=
,它将被保留:$ IFS= read -r line <<< " test "
$ printf "<%s>\n" "$line"
< test >
$ read -r line <<< " test "
$ printf "<%s>\n" "$line"
<test>
你可以想象第一个非IFS=
循环对于Python文件会造成多大的破坏。
cat foo | bar
比bar <foo
(1)低效,有两个原因:(1a)创建管道需要额外的fork();(1b)导致foo
首先由cat
读取,然后写入管道,然后由bar
从管道中读取,而不是直接让foo
中的内容被bar
直接读取。在(2)中,如果bar
是一个可以访问seek()
调用的程序(通常对于bash不可用,除非你编写了C扩展),给它一个管道而不是一个文件会防止使用它。 - Charles DuffyIFS=
吗? - that other guy