我一直在到处修改 IFS 的内容,但无法解释不同代码片段的行为,归结为:
$ read -r < <(printf "%s\n" " x ") && echo \<"$REPLY"\>
< x >
$ read -r line < <(printf "%s\n" " x ") && echo \<"$line"\>
<x>
当然man bash
该有的都有了。
如果没有提供姓名,读取的行被分配给变量 REPLY。返回码为零,除非遇到文件结尾、读取超时(此时返回码大于 128)、发生变量赋值错误(例如赋值给只读变量)或无效文件描述符作为 -u 的参数提供。
我只是觉得如果那些与 IFS 相关的答案之一包含有关此的一句话就好了理由。事实证明,有些甚至是公开错误的。一个例子是本段中的编辑这个答案:
除非使用参数调用 IFS,否则 read 不会使用 IFS。 (编辑:这并不完全正确:IFS 中存在的空白字符(即空格和制表符)在输入行的开头/结尾处始终被忽略。 )
这是一个没有问号的反问句。但如果我错了,请纠正我等等。
答案1
所有 Bourne/POSIX shell(dash、ksh、pdksh、mksh、bash、zsh,即使不在 sh 模拟模式下、BusyBox sh、Bourne shell 等)遵循的正常行为是read -r line
删除前导和尾随空白字符。更一般地,read -r line
从 中删除由任意数量的空白字符组成的前导分隔符,IFS
并且最多从 中删除一个非空白字符IFS
。在行的末尾,只有空白字符可以被删除,因为如果该行以非空白分隔符结束,那么它将以空字段结束。这是更一般情况的特殊情况:第一个变量获取第一个字段,第二个变量获取第二个字段,依此类推,如果字段多于变量,则最后一个变量获取行的其余部分,除了尾随空白。
使用隐式变量名进行调用read
是 bash 和 zsh 模仿的 ksh 扩展。在 ksh(ATT 和 pdksh/mksh)和 zsh 中,没有变量名与有变量名read
完全相同。在 bash 中,由于某种原因,行为有所不同:当变量名是隐式的时,不会进行空格剥离。这是有意而为之的,但我不知道做出不同的理由。 (如果您不想剥离,标准方法是运行。)read
REPLY
IFS
IFS= read -r
/* If there are no variables, save the text of the line read to the
variable $REPLY. ksh93 strips leading and trailing IFS whitespace,
so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
same way, but I believe that the difference in behaviors is useful
enough to not do it. Without the bash behavior, there is no way
to read a line completely without interpretation or modification
unless you mess with $IFS (e.g., setting it to the empty string).
If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
if (list == 0)
{
#if 0
orig_input_string = input_string;
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t
;
input_string = t;
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw
#endif