传送到命令后尾随新行:有任何标准吗?

Trailing new line after piping to a command: is there any standard?

回答 我发现有些程序确实会在字符串末尾添加尾随换行符,而其他程序则不会:

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

$ printf "foobar" | od -c
0000000   f   o   o   b   a   r
0000006

echo -n:

$ echo -n "foobar" | od -c
0000000   f   o   o   b   a   r
0000006

(echo 的默认行为是 return 输出后跟一个换行符,所以 echo "foobar" returns f o o b a r \n).

sedcat 都没有添加任何额外的字符:

$ 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

awkcut 都可以。另外 xargspaste 添加这个尾随的新行:

$ 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

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

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

So I was wondering: why is this different behaviour? Is there anything POSIX suggests about this?

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

从 POSIXv7 的 Definitions 开始,文本行的末尾必须有一个 newline

3.206 Line

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

如果缺少newline,则变成这样:

3.195 Incomplete Line

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

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

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