根据手册页中的“阅读-N”说明:
-N nchars仅在读取NCHARS字符后返回,除非遇到EOF或读取超时,忽略任何分隔符
但是,在回答以下命令时:
$ echo 'a b' | while read -N1 c; do echo ">>>$c<<<"; done
>>>a<<<
>>><<<
>>>b<<<
>>><<<
两者,空格和换行符都被翻译成空字符串,而在命令中:
$ echo 'a b' | while IFS= read -N1 c; do echo ">>>$c<<<"; done
>>>a<<<
>>> <<<
>>>b<<<
>>>
<<<
空格和换行符已正确存储在变量中。
所以,似乎分隔符在“read”或“while”命令中仍有一些处理,我不明白。
我们可以将这些结果与使用“read -n”的结果进行比较,该手册描述为:
-n nchars在读取NCHARS字符后返回而不是等待换行符,但如果在分隔符之前读取的NCHARS字符少于,则表示分隔符
$ echo 'a b' | while read -n1 c; do echo ">>>$c<<<"; done
>>>a<<<
>>><<<
>>>b<<<
>>><<<
$ echo 'a b' | while IFS= read -n1 c; do echo ">>>$c<<<"; done
>>>a<<<
>>> <<<
>>>b<<<
>>><<<
答案 0 :(得分:4)
这是POSIX行为。分配给变量时,应剥离IFS字符:结果应分割成字段,如shell中的参数扩展结果(当然,-n和-N不是POSIX)。
这是由read
源代码注释产生的:
/* This code implements the Posix.2 spec for splitting the words
read and assigning them to variables. */
orig_input_string = input_string;
/* Remove IFS white space at the beginning of the input string. If
$IFS is null, no field splitting is performed. */
答案 1 :(得分:3)
在我看来,在使用选项-N
时,read
的行为在
当它读取一个字符时,分隔符的处理方式与非分隔符相同,read
将对它们进行计数。但是,当read
分配分隔符时,它会认为如果读取输入是分隔符,如果它是分隔符,则它会为相应的变量赋予空值。
因此,IFS=
将改变为变量分配空格的行为,并将空格分配给c
而不是空。
答案 2 :(得分:2)
使用hexdump
可以让我们准确查看构成输出的字符,因此略微更改查询可能会有所帮助:
(1)使用正常IFS并使用-N选项
$ (echo 'a b' | while read -N1 c; do c="$c<"; echo -n "$c"; done | hexdump -C)
00000000 61 3c 3c 62 3c 3c |a<<b<<|
00000006
在第一种情况下,0x0a
和空格字符的内置读取返回空字符串,因为字符在默认IFS中,IFS中的字符在输出中被忽略,原因在于cdarke&回答。
(2)空IFS和-N选项
$ (IFS=""; echo 'a b' | while read -N1 c; do c="$c<"; echo -n "$c"; done | hexdump -C)
00000000 61 3c 20 3c 62 3c 0a 3c |a< <b<.<|
00000008
在这种情况下,read内置将匹配echo命令输出的四个字符中的每一个,并且在输出中看到0x0a
和空格,因为对于空IFS,可以分配读取的字符到局部变量c
。
(3)使用正常的IFS和-n选项
$ (echo 'a b' | while read -n1 c; do c="$c<"; echo -n "$c"; done | hexdump -C)
00000000 61 3c 3c 62 3c 3c |a<<b<<|
00000006
这给出与case(1)相同的输出,尽管语义有点不同:0x0a
和空格字符的内置读取返回空字符串,因为(i)这两个字符在默认的IFS和(ii)读取内置的-n选项在任何情况下都不会传递尾随的0x0a
字符
(4)空IFS和-n选项
$ (IFS=""; echo 'a b' | while read -n1 c; do c="$c<"; echo -n "$c"; done | hexdump -C)
00000000 61 3c 20 3c 62 3c 3c |a< <b<<|
00000007
在这里我们观察到-n和-N选项之间的区别:使用-n选项,换行特意处理读取内置并删除换行符,因此从IFS中排除0x0a
并不# 39; t有机会将其传递给局部变量c
。