我正在处理一个小文本文件,其中包含我要添加新单词的单词列表,然后排序。我开始时文件末尾没有换行符,但排序后却没有换行符。为什么?我可以避免这种行为,还是有办法将换行删除?
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
答案 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"末尾的字符。 ,sed
,perl
,php
,甚至是原始bash
。这在其他地方有所涉及,例如:
How can I remove the last character of a file in unix?
但请不要这样做。您只会导致所有其他必须处理您文件的实用程序出现问题,例如排序。如果你假设文件中没有终止换行符,那么你将使代码变得脆弱:工具链的任何部分都会修复"修复"你的错误(就像在这里排序一样)会"打破"你的代码。
相反,将文本文件视为在unix中处理它们的方式:一系列" line" (零个或多个非换行字节的字符串),每个字符后跟一个换行符。
所以新行是行终止符,而不是行分隔符。
有一种编码风格,其中print
和echo
s用换行符引导完成。出于多种原因这是错误的,包括创建格式错误的文本文件,以及使程序的输出与命令提示符连接在一起。 printf "orange\n"
是正确的风格,也更具可读性:一眼认识维护您的代码的人可以告诉您重新打印单词" orange"和换行符一样,而printf "\norange"
乍一看就像它打印一个反斜杠和短语"没有范围"缺少空间。