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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26479562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:42:42  来源:igfitidea点击:

What does IFS= do in this bash loop: `cat file | while IFS= read -r line; do ... done`

bashifs

提问by bodacydo

I'm learning bash and I saw this construction:

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

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

Can anyone explain what IFS=does? I know it's input field separator, but why is it being set to nothing?

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

回答by John1024

IFSdoes many things but you are asking about that particular loop.

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

The effect in that loop is to preserve leading and trailing white spacein line. To illustrate, first observe with IFS set to nothing:

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

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

The linevariable contains all the white space it received on its stdin. Now, consider the same statement with the default IFS:

line变量包含它在其标准输入上收到的所有空白。现在,考虑使用默认 IFS 的相同语句:

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

In this version, the white space internal to the line is still preserved. But, the leading and trailing white space have been removed.

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

What does -rdo in read -r?

-r做什么read -r

The -roption prevents readfrom treating backslash as a special character.

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

To illustrate, we use two echo commands that supply two lines to the whileloop. Observe what happens with -r:

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

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

Now, observe what happens without -r:

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

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

Without -r, two changes happened. First, the double-backslash was converted to a single backslash. Second, the backslash on the end of the first line was interpreted as a line-continuation character and the two lines were merged into one.

没有-r,发生了两个变化。首先,双反斜杠被转换为单反斜杠。其次,第一行末尾的反斜杠被解释为行继续符,两行合并为一行。

In sum, if you want backslashes in the input to have special meaning, don't use -r. If you want backslashes in the input to be taken as plain characters, then use -r.

总之,如果您希望输入中的反斜杠具有特殊含义,请不要使用-r. 如果您希望将输入中的反斜杠视为纯字符,请使用-r.

Multiple lines of input

多行输入

Since readtakes input one line at a time, IFS behaves affects each line of multiple line input in the same way that it affects single line input. -rbehaves similarly with the exception that, without -r, multiple lines can be combined into one line using the trailing backslash as shown above.

由于一次read输入一行,IFS 的行为会影响多行输入的每一行,就像它影响单行输入一样。 -r行为类似,不同之处在于,如果没有-r,可以使用尾随反斜杠将多行合并为一行,如上所示。

The behavior with multiple line input, however, can be changed drastically using read's -dflag. -dchanges the delimiter character that readuses to mark the end of an input line. For example, we can terminate lines with a tab character:

但是,可以使用 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=

Here, the $'...'construct was used to enter special characters like newline, \nand tab, \t. Observe that with -d$'\t', readdivides its input into "lines" based on tab characters. Anything after the final tab is ignored.

此处,该$'...'构造用于输入特殊字符,例如换行符\n和制表符、\t. 请注意,使用-d$'\t',read根据制表符将其输入分为“行”。最后一个选项卡之后的任何内容都将被忽略。

How to handle the most difficult file names

如何处理最难的文件名

The most important use of the features described above is to process difficult file names. Since the one character that cannot appear in path/filenames is the null character, the null character can be used to separate a list of file names. As an example:

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

while IFS= read -r -d $'##代码##' file
do
    # do something to each file
done < <(find ~/music -type f -print0)