sort -o将换行符附加到文件末尾 - 为什么?

时间:2018-01-08 16:01:28

标签: bash sorting

我正在处理一个小文本文件,其中包含我要添加新单词的单词列表,然后排序。我开始时文件末尾没有换行符,但排序后却没有换行符。为什么?我可以避免这种行为,还是有办法将换行删除?

实施例

words.txt看起来像

apple
cookie
salmon

然后我运行printf "\norange" >> words.txt; sort words.txt -o words.txt

我使用printf而不是echo来确定是否会避免换行,但文件会读取

apple
cookie
orange
salmon
#newline here

如果我只是运行printf "\norange" >> words.txt橙色出现在文件的底部,没有换行符,即;

apple
cookie
salmon
orange

2 个答案:

答案 0 :(得分:7)

此行为在the POSIX specification for sort

中明确定义
  

输入文件应该是文本文件,除了sort实用程序应该在以不完整的最后一行结尾的文件末尾添加换行符。

因为UNIX“文本文件”仅在所有行以换行符结尾时有效,如also defined in the POSIX standard

  

文本文件 - 包含组织为零行或多行的字符的文件。这些行不包含NUL字符,并且没有一行可以超过{LINE_MAX}个字节,包括换行符。尽管POSIX.1-2008不区分文本文件和二进制文件(请参阅ISO C标准),但许多实用程序在操作文本文件时仅产生可预测或有意义的输出。具有此类限制的标准实用程序始终在其STDIN或INPUT FILES部分中指定“文本文件”。

答案 1 :(得分:5)

考虑一下你要sort要做什么。

你问它"采取所有行,并按顺序排序。"

您已经为它提供了一个包含四行的文件,并将其拆分为以下字符串:

"salmon\n"
"cookie\n"
"orange"

它尽职尽责地为您排序:

"cookie\n"
"orange"
"salmon\n"

然后它将它们作为单个字符串输出:

"cookie
orangesalmon
"

这几乎可以肯定是你不想要的。

相反,如果您的文件缺少应该有的终止换行符,那么sort程序就会明白,您很可能仍然认为最后一行是一行而不仅仅是一条线的片段。它将\ n附加到字符串" orange",使其成为" orange \ n"。然后它可以正确分类,没有"橙"在它之后发生的任何一行都会连接起来:

"cookie\n"
"orange\n"
"salmon\n"

因此,当它将它们作为单个字符串输出时,它看起来好多了:

"cookie
orange
salmon
"

可以使用一系列方便的工具(例如awk)删除文件中的最后一个字符,即" salmon \ n"末尾的字符。 ,sedperlphp,甚至是原始bash。这在其他地方有所涉及,例如:

How can I remove the last character of a file in unix?

但请不要这样做。您只会导致所有其他必须处理您文件的实用程序出现问题,例如排序。如果你假设文件中没有终止换行符,那么你将使代码变得脆弱:工具链的任何部分都会修复"修复"你的错误(就像在这里排序一样)会"打破"你的代码。

相反,将文本文件视为在unix中处理它们的方式:一系列" line" (零个或多个非换行字节的字符串),每个字符后跟一个换行符。

所以新行是行终止符,而不是行分隔符。

有一种编码风格,其中printecho s用换行符引导完成。出于多种原因这是错误的,包括创建格式错误的文本文件,以及使程序的输出与命令提示符连接在一起。 printf "orange\n"是正确的风格,也更具可读性:一眼认识维护您的代码的人可以告诉您重新打印单词" orange"和换行符一样,而printf "\norange"乍一看就像它打印一个反斜杠和短语"没有范围"缺少空间。

相关问题