我正在学习Bash,看到了以下语法结构:
cat file | while IFS= read -r line;
do
...
done
有人能解释一下IFS=
是什么意思吗?我知道它是输入字段分隔符,但为什么要将其设置为空?
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=
在这个版本中,行内的空格仍然被保留。但是,前导和尾随的空格已经被删除。
-r
在 read -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
,则可以使用末尾的反斜杠将多行组合成一行,如上所示。-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)
IFS=
基本上是将IFS
设置为空。在您的情况下,它将与IFS=$'\n'
相同。 - anubhava