在这个Bash循环中,IFS=的作用是什么:`cat file | while IFS= read -r line; do ... done`?

67

我正在学习Bash,看到了以下语法结构:

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

有人能解释一下IFS=是什么意思吗?我知道它是输入字段分隔符,但为什么要将其设置为空?


3
IFS=基本上是将IFS设置为空。在您的情况下,它将与IFS=$'\n'相同。 - anubhava
这是一个简单的问题,你可以向之前回答问题的人(@Chepner)提问。 - Avinash Raj
@anubhava 谢谢。所以如果IFS为空,那么它就相当于换行符? - bodacydo
显示剩余2条评论
1个回答

129

IFS 可以完成许多任务,但您现在询问的是特定循环。

该循环的效果是保留line前导和尾随空格。为了说明这一点,首先观察当 IFS 设置为空时:

$ echo " this   is a test " | while IFS= read -r line; do echo "=$line=" ; done
= this   is a test =

line变量包含从标准输入中接收到的所有空格。现在,考虑使用默认IFS的相同语句:

$ echo " this   is a test " | while read -r line; do echo "=$line=" ; done
=this   is a test=

在这个版本中,行内的空格仍然被保留。但是,前导和尾随的空格已经被删除。

-rread -r 中的作用是什么?

-r 选项防止 read 将反斜杠视为特殊字符。

为了说明这一点,我们使用两个 echo 命令来向 while 循环提供两行。观察在使用 -r 时会发生什么:

$ { echo 'this \\ line is \' ; echo 'continued'; } | while IFS= read -r line; do echo "=$line=" ; done
=this \\ line is \=
=continued=

现在,观察一下没有 -r 的情况会发生什么:
$ { echo 'this \\ line is \' ; echo 'continued'; } | while IFS= read line; do echo "=$line=" ; done
=this \ line is continued=

没有使用-r,发生了两个更改。首先,双反斜杠被转换为单反斜杠。其次,第一行末尾的反斜杠被解释为换行符,并将这两行合并为一行。
总之,如果您希望输入中的反斜杠具有特殊含义,请不要使用-r。如果您希望输入中的反斜杠被解释为普通字符,则使用-r
多行输入
由于read逐行获取输入,因此IFS以与单行输入相同的方式影响每行多行输入。但是,使用-r时会有所不同,唯一的例外是,如果没有使用-r,则可以使用末尾的反斜杠将多行组合成一行,如上所示。
但是,使用read的-d标志可以大大改变多行输入的行为。 -d更改read用于标记输入行结尾的分隔符字符。例如,我们可以使用制表符作为行终止符。
$ echo $'line one \n line\t two \n line three\t ends here'
line one 
 line    two 
 line three      ends here
$ echo $'line one \n line\t two \n line three\t ends here' | while IFS= read -r -d$'\t' line; do echo "=$line=" ; done
=line one 
 line=
= two 
 line three=

这里使用$'...'结构来输入特殊字符,如换行符\n和制表符\t。请注意,使用-d$'\t'read会根据制表符将其输入分成“行”。最后一个制表符后面的任何内容都会被忽略。

如何处理最困难的文件名

上述功能的最重要用途是处理困难的文件名。由于在路径/文件名中不能出现空字符,因此可以使用空字符来分隔文件名列表。例如:
while IFS= read -r -d $'\0' file
do
    # do something to each file
done < <(find ~/music -type f -print0)

这很有用。任何关于shell中循环结构的问题也应该参考为什么使用shell循环处理文本被认为是不良实践,在那里所有都会变得清晰明了... - Ed Morton
1
这是 G.O.A.T。 - oyeshetty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接