读取 -r 与读取 -r 行和 IFS

读取 -r 与读取 -r 行和 IFS

我一直在到处修改 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 中,由于某种原因,行为有所不同:当变量名是隐式的时,不会进行空格剥离。这是有意而为之的,但我不知道做出不同的理由。 (如果您不想剥离,标准方法是运行。)readREPLYIFSIFS= 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

相关内容