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
What does IFS= do in this bash loop: `cat file | while IFS= read -r line; do ... done`
提问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
IFS
does 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 line
variable 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 -r
do in read -r
?
在-r
做什么read -r
?
The -r
option prevents read
from treating backslash as a special character.
该-r
选项可防止read
将反斜杠视为特殊字符。
To illustrate, we use two echo commands that supply two lines to the while
loop. 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 read
takes 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. -r
behaves 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 -d
flag. -d
changes the delimiter character that read
uses 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, \n
and tab, \t
. Observe that with -d$'\t'
, read
divides 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)