我一直wc -l
在检查文件中存在的行数。它一直工作得很好,但这次不行。
我有 120 个大文件,每个文件应该至少有两行。我刚刚对这些文件进行了一些文本编辑工作,以删除和添加新行。我试图wc -l *
像往常一样使用来检查最终的行数。输出显示大多数文件只有一行。
我打开了其中一个文件(从命令结果显示它只有一行),vim
我可以看到它正好有 2 行。退出vim
并使用 再次检查wc -l
,该文件的行数显示为 2。
有人知道这里发生了什么吗?我怎样才能解决这个问题而不是用打开所有 120 个文件vim
?
PS:我的文件的最后一行不是空的。
答案1
常见的 gnu 实现wc
说
'wc' 计算每个给定 FILE 中的字节数、字符数、空格分隔的单词数
和换行符数,如果没有给出或 FILE 为 '-',则计算标准输入数。
因此,如果文件中没有最后的换行符,则输出的“行”部分wc
将比预期少 1。例如下面将输出 1
printf 'hello\nworld' | wc -l
OP 在评论中确认 vim 正在报告缺少最终换行符。如果已知所有文件都存在此问题,一个简单的修复方法是
for f in *
do
echo >> "$f"
done
向每个文件附加换行符。
如果所有文件缺少换行符,有条件地在其末尾添加换行符的一种方法是使用 sed。
sed -s -i '$s/$/\n/;P;d' *
使用一些 GNU 扩展,-s
分别处理每个文件,-i
进行就地编辑,并允许\n
表示换行符。 sed 程序本身表示在每个文件的最后一行附加一个换行符,并为每一行打印到第一个换行符并移至下一行。
答案2
这并不完全是一个答案,而是分享一个我经常使用的微型个人工具来标准化文本文件(txtnorm):
#!/usr/bin/perl -spi
our($s);
s/\n\r|\r\n|\n|\r/\n/g; ## normalize \n
s/^(\xFF\xFE|\xFE\xFF|\xEF\xBB\xBF)//; ## remove BOM !
s/(?<=.)\z/\n/; ## ensure newline at eof
if($s){ s/\xC2\xA0/ /g } ## -s non breaking spaces-> " "
txtnorm *.txt
标准化行尾,确保 eof 处换行,删除 BOM 并(使用 -s)可以标准化不间断空格。
请务必仅在文本文件上使用它。