【问题标题】:What does IFS= do in this bash loop: `cat file | while IFS= read -r line; do ... done`IFS= 在这个 bash 循环中做了什么:`cat file |而 IFS= 读取 -r 行;做...完成`
【发布时间】:2014-12-16 06:09:34
【问题描述】:

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

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

谁能解释IFS= 的作用?我知道它是输入字段分隔符,但为什么它被设置为空?

【问题讨论】:

标签: bash ifs


【解决方案1】:

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)

【讨论】:

猜你喜欢
  • 2022-01-22
  • 2020-10-03
  • 2014-10-27
  • 1970-01-01
  • 2018-08-12
  • 1970-01-01
  • 2018-12-05
相关资源
最近更新 更多