Answers:
某些人有错误的概念,read即读取行的命令。不是。
read从(可能是反斜杠连续的)行中读取单词,其中的单词是$IFS定界的,反斜杠可用于转义定界符(或继续行)。
通用语法为:
read word1 word2... remaining_wordsread一次读取标准输入一个字节直到找到一个未转义换行符(或输入结束),分裂,根据复杂的规则并存储分割的结果为$word1,$word2... $remaining_words。
例如在类似的输入上:
  <tab> foo bar\ baz   bl\ah   blah\
whatever whatever并用默认值$IFS,read a b c将会分配:
$a ⇐ foo$b ⇐ bar baz$c ⇐ blah   blahwhatever whatever现在,如果仅传递一个参数,则不会变为read line。还在read remaining_words。反斜杠处理仍然完成,IFS空格字符仍从开头和结尾删除。
该-r选项删除反斜杠处理。所以上面的相同命令-r将分配
$a ⇐ foo$b ⇐ bar\$c ⇐ baz   bl\ah   blah\现在,对于拆分部分,重要的是要认识到有两类字符$IFS:IFS空格字符(即空格和制表符(以及换行符,尽管在这里除非使用-d无关紧要),否则也会发生)设为$IFS)和其他默认值。这两类字符的处理方式不同。
随着IFS=:(:是不是IFS空白字符),如输入:foo::bar::将被分裂成"","foo","",bar和""(和一个额外的""一些实现方式虽然不除无所谓read -a)。如果将其替换:为空格,则拆分为only foo和bar。那就是前导和尾随的被忽略,并且它们的序列被视为一个。将中的空白字符和非空白字符结合使用时,还有其他规则$IFS。一些实现可以通过将IFS中的字符加倍(IFS=::或IFS='  ')来添加/删除特殊处理。
因此,在这里,如果我们不希望删除开头和结尾的未转义的空白字符,则需要从IFS中删除那些IFS空白字符。
即使使用IFS非空白字符,如果输入行包含这些字符中的一个(只有一个),并且它是该行中的最后一个字符(IFS=: read -r word例如foo:),则使用POSIX shell(不是zsh某些pdksh版本),该输入之所以被视为一个foo单词,是因为在这些shell中,这些字符$IFS被视为终结符,因此word将包含foo,而不是foo:。
因此,使用read内置方法读取一行输入的规范方法是:
IFS= read -r line(请注意,对于大多数read实现,该方法仅适用于文本行,因为除中不支持NUL字符zsh)。
使用var=value cmd语法可确保IFS仅在该cmd命令期间设置不同的设置。
该read内置由Bourne shell的引入,已经读的话,而不是行。现代POSIX外壳有一些重要的区别。
Bourne shell read不支持-r选项(这是Korn shell引入的),因此除了使用类似的东西对输入进行预处理之外,没有其他方法可以禁用反斜杠处理sed 's/\\/&&/g'。
Bourne shell没有两类字符的概念(再次由ksh引入)。在Bourne Shell中,所有字符都与ksh中的IFS空格字符进行相同的处理,即IFS=: read a b c在输入foo::bar上将类似分配bar给$b,而不是空字符串。
在Bourne shell中,具有:
var=value cmd如果cmd是内置的(如readis),则在完成后var仍设置为。这一点特别重要,因为在Bourne shell中,它用于拆分所有内容,而不仅仅是扩展。另外,如果您从Bourne外壳程序中删除空格字符,将不再起作用。valuecmd$IFS$IFS$IFS"$@"
在Bourne Shell中,重定向复合命令会使它在子Shell中运行(在最早的版本中,即使类似read var < file或exec 3< file; read var <&3不起作用的东西),因此在Bourne Shell中很少read用于除终端上的用户输入以外的任何内容(在该行继续处理有意义的地方)
某些Unices(例如HP / UX,也有in in util-linux)仍然具有line读取一行输入的命令(在Single UNIX Specification版本2之前,它一直是标准UNIX命令)。
基本上与一次head -n 1读取相同,只是一次读取一个字节以确保读取的行不超过一行。在这些系统上,您可以执行以下操作:
line=`line`当然,这意味着产生一个新进程,执行一个命令并通过管道读取其输出,因此效率比ksh差IFS= read -r line很多,但仍然更加直观。
sh差异之间的洞察力对于编写可移植脚本也很有用!)
                    bash-4.4.19,while read -r; do echo "'$REPLY'"; done起作用while IFS= read -r line; do echo "'$line'"; done。
                    read读取行是错误的,则还必须有其他东西。这个无误的概念是什么?还是从技术上来说,第一个语句是正确的,但实际上,无误的概念是:“ read是从一行中读取单词的命令。由于它功能如此强大,您可以通过执行以下操作从文件中读取行:IFS= read -r line”
                    这里有两个概念在起作用:
IFS是输入字段分隔符,这表示将根据中的字符对读取的字符串进行分割IFS。在命令行上,IFS通常是空格字符,这就是命令行在空格处分割的原因。VAR=value command意味着“修改命令环境,使其VAR具有值value”。基本上,该命令command将VAR具有值value,但此后执行的任何命令仍将VAR具有其先前的值。换句话说,将仅针对该语句修改该变量。因此,在执行操作时IFS= read -r line,您正在将其设置IFS为一个空字符串(不使用任何字符来拆分,因此不会进行拆分),以便read读取整行并将其视为分配给line变量的一个单词。IFS所做的更改仅影响该语句,因此所有后续命令都不会受到更改的影响。
虽然该命令是正确的,并会工作打算,设置IFS在这种情况下是不是 强权1没有必要。如内置部分的bash手册页中所述read:
从标准输入中读取一行,并将第一个单词分配给名字,第二个单词分配给名字,依此类推,剩下的单词及其中间的分隔符分配给姓氏。如果从输入流中读取的单词少于名称,则为其余名称分配空值。中的字符
IFS用于将行拆分为单词。[...]
由于您只有line变量,因此无论如何都会为每个单词赋值,因此,如果不需要任何前面和结尾的空白字符1,则只需编写read -r line并完成操作即可。
[1]举例来说,一个unset或默认$IFS值将如何导致read使用引导/跟踪IFS空格,您可以尝试:
echo ' where are my spaces? ' | { 
    unset IFS
    read -r line
    printf %s\\n "$line"
} | sed -n l运行它,您会发现,如果IFS未设置,则前面和后面的字符将无法生存。此外,如果$IFS要在脚本的较早位置进行修改,可能会发生一些奇怪的事情。
您应该分两部分阅读该语句,第一部分清除IFS变量的值,即等同于更具可读性IFS="",第二部分line从stdin中读取变量read -r line。
此语法的特定之处在于IFS的影响是过时的,仅对read命令有效。
除非我丢失了某些内容,否则在特定情况下,清除IFS不会起作用,尽管无论IFS设置为什么,整行都将在line变量中读取。仅在将多个变量作为参数传递给read指令的情况下,行为才会发生变化。
编辑:
的-r是有允许输入与截至\进行特殊加工不,即,对于要被包括在所述反斜线line变量,而不是作为连续符,以允许多行输入。
$ read line; echo "[$line]"   
abc\
> def
[abcdef]
$ read -r line; echo "[$line]"  
abc\
[abc\]清除IFS具有防止读取以修剪潜在的前导和尾随空格或制表符的副作用,例如:
$ echo "   a b c   " | { IFS= read -r line; echo "[$line]" ; }   
[   a b c   ]
$ echo "   a b c   " | { read -r line; echo "[$line]" ; }     
[a b c]感谢rici指出了这种差异。
read -r line则在将输入分配给line变量之前将修剪前导和尾随空格。
                    IFS= read a b <<< 'aa bb' ; echo "-$a-$b-"将显示-aa bb--