管道到命令后跟踪新行:是否有任何标准?

fed*_*qui 5 unix bash posix gnu

回答如何删除最后一个CR charcut我发现有些程序确实在字符串末尾添加了一个尾随的新行,而其他程序则没有:

假设我们有字符串foobar并打印出来,printf这样我们就不会得到额外的新行:

$ printf "foobar" | od -c
0000000   f   o   o   b   a   r
0000006
Run Code Online (Sandbox Code Playgroud)

或者echo -n:

$ echo -n "foobar" | od -c
0000000   f   o   o   b   a   r
0000006
Run Code Online (Sandbox Code Playgroud)

(echo默认行为是返回输出后跟换行符,因此echo "foobar"返回f o o b a r \n).

sed没有cat添加任何额外的字符:

$ printf "foobar" | sed 's/./&/g' | od -c
0000000   f   o   o   b   a   r
0000006
$ printf "foobar" | cat - | od -c
0000000   f   o   o   b   a   r
0000006
Run Code Online (Sandbox Code Playgroud)

而这两个awkcut做.另外xargs,paste添加这个尾随的新行:

$ printf "foobar" | cut -b1- | od -c
0000000   f   o   o   b   a   r  \n
0000007
$ printf "foobar" | awk '1' | od -c
0000000   f   o   o   b   a   r  \n
0000007
$ printf "foobar" | xargs | od -c
0000000   f   o   o   b   a   r  \n
0000007
$ printf "foobar" | paste | od -c
0000000   f   o   o   b   a   r  \n
0000007
Run Code Online (Sandbox Code Playgroud)

所以我想知道:为什么这种行为不同?POSIX对此有何建议?

注意我在Bash 4.3.11中运行所有这些,其余的是:

  • GNU Awk 4.0.1
  • sed(GNU sed)4.2.2
  • cat(GNU coreutils)8.21
  • cut(GNU coreutils)8.21
  • xargs(GNU findutils)4.4.2
  • paste(GNU coreutils)8.21

Dum*_*001 2

所以我想知道:为什么会有这种不同的行为?POSIX对此有什么建议吗?

一些命令(例如)是库调用(例如)printf的简单接口,不会自动添加。大多数 *NIX 文本处理命令会在最后一行末尾添加。libcprintf()\n\n

根据POSIXv7 的定义newline,文本行末尾必须有一个:

3.206线

<newline>零个或多个非字符加上终止字符的序列。

如果newline缺少的话,就会变成这样:

3.195 不完整线

<newline>文件末尾的一个或多个非字符序列。

总体思路是文本文件可以被视为记录列表,其中每个记录都以\n. 换句话说,\n不是线条之间的东西——它是线条的一部分。例如,参见fgets()函数: the\n始终包含在内,用于识别文本行是否已完全读取的情况。如果最后一行缺少\n,则必须进行更多检查才能正确读取文件。

一般来说,只要您的文本文件是由 *NIX 程序/脚本在 *NIX 上创建的,就可以期望最后一行正确终止。但许多 Java 应用程序以及 Windows 应用程序不能正确或一致地处理该问题。他们不仅经常忘记添加最后一个\n,而且常常错误地将尾随\n视为额外的空行。