【问题标题】:sort -o appends newline to end of file - why?sort -o 将换行符附加到文件末尾 - 为什么?
【发布时间】:2018-01-08 16:01:27
【问题描述】:

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

示例:

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

【问题讨论】:

  • sort 表示它在帮您一个忙。我的总是报告sort: warning: newline appendedsort 的不同版本有不同的功能。梳理可用版本的手册页,也许你会找到一个 cmd-arg --no-newline 或类似的。将来请将此类与编程无关的 Q(恕我直言)发布到 unix.stackexchange.comsuperuser.com 。祝你好运。
  • 没有尾随换行符的“文本文件”不是有效的 UNIX 文本文件。许多工具会直接忽略任何没有尾随换行符的行——例如,任何BashFAQ #1 while read 循环都会在这些行上退出而不是处理它们。
  • 顺便说一句,单个尾随换行符不会创建一个空行(正如您在此处呈现的那样) - 它只是确保它之前的行是完整的,即。不要让光标悬空等待更多内容,或者让程序阅读器不清楚文件是否已完全刷新。

标签: bash sorting


【解决方案1】:

此行为在the POSIX specification for sort 中明确定义:

输入文件应为文本文件,但排序实用程序应在以不完整的最后一行结尾的文件末尾添加换行符。

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

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

【讨论】:

  • 不错。为索赔提供实际参考是应该的答案,现在我为不这样做而感到难过。
【解决方案2】:

想想你要求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
"

可以使用一系列方便的工具,例如awksed、@987654331,从文件中删除最后一个字符,即“salmon\n”末尾的那个字符@、php,甚至是原始的bash。这在其他地方都有介绍,例如:

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

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

相反,应按照在 unix 中的处理方式处理文本文件:一系列“行”(零个或多个非换行字节的字符串),每个后跟一个换行符。

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

有一种编码风格,其中prints 和echos 以​​换行符开头。这是错误的,原因有很多,包括创建格式错误的文本文件,以及导致程序的输出与命令提示符连接。 printf "orange\n" 是正确的风格,也更易读:乍一看,维护您的代码的人可以告诉您正在打印单词“orange”和换行符,而 printf "\norange" 乍一看像是在打印反斜杠和短语缺少空格的“无范围”。

【讨论】:

  • 感谢您的解释!现在很有意义
  • 您似乎在“any part of the”之后删除了一些文字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 2020-08-25
  • 2015-02-02
  • 1970-01-01
相关资源
最近更新 更多