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

bod*_*ydo 25 bash ifs

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

cat file | while IFS= read -r line;
do
    ...
done
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*024 54

IFS 做了很多事,但你问的是那个特定的循环.

在这个循环的作用是保持领先和尾随空白line.为了说明,首先观察IFS设置为空:

$ echo " this   is a test " | while IFS= read -r line; do echo "=$line=" ; done
= this   is a test =
Run Code Online (Sandbox Code Playgroud)

line变量包含它在stdin上收到的所有空白区域.现在,考虑使用默认IFS的相同语句:

$ echo " this   is a test " | while read -r line; do echo "=$line=" ; done
=this   is a test=
Run Code Online (Sandbox Code Playgroud)

在此版本中,线条内部的空白区域仍保留.但是,已删除了前导和尾随空白区域.

-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=
Run Code Online (Sandbox Code Playgroud)

现在,观察没有发生的事情-r:

$ { echo 'this \\ line is \' ; echo 'continued'; } | while IFS= read line; do echo "=$line=" ; done
=this \ line is continued=
Run Code Online (Sandbox Code Playgroud)

没有-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=
Run Code Online (Sandbox Code Playgroud)

这里,$'...'构造用于输入特殊字符,如换行符\n和制表符\t.观察,使用-d$'\t',read根据制表符将其输入划分为"行".忽略最终选项卡后的任何内容.

如何处理最困难的文件名

上述功能最重要的用途是处理困难的文件名.由于无法在路径/文件名中出现的一个字符是空字符,因此空字符可用于分隔文件名列表.举个例子:

while IFS= read -r -d $'\0' file
do
    # do something to each file
done < <(find ~/music -type f -print0)
Run Code Online (Sandbox Code Playgroud)

  • 我为此悬赏,以奖励这一明确的解释。非常感谢! (3认同)
  • @fedorqui 感谢您注意到并欣赏这个旧答案! (3认同)