IFS =在这个bash循环中做了什么:`cat file |而IFS =读-r线;做...完成

时间:2014-10-21 05:37:27

标签: bash ifs

我正在学习bash,我看到了这种结构:

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

任何人都可以解释IFS=的作用吗?我知道它的输入字段分隔符,但为什么它被设置为空?

1 个答案:

答案 0 :(得分:44)

IFS会做很多事情,但是你在问这个特定的循环。

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

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

line变量包含它在stdin上收到的所有空白区域。现在,考虑使用默认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)