比 wc -l 更快、更精确地计算行数的方法
Posted
技术标签:
【中文标题】比 wc -l 更快、更精确地计算行数的方法【英文标题】:Faster and precise way to count lines other than wc -l 【发布时间】:2014-08-01 07:28:43 【问题描述】:通常我使用wc -l
来计算文件的行数。但是,对于具有 5*10^7 行的文件,我只得到 10^7 作为答案。
我已经尝试了这里提出的一切:
How to count lines in a document?
但这比wc -l
要花很多时间。
还有其他选择吗?
【问题讨论】:
你从哪里得到的文件,有 DOS/UNIX 换行问题吗?awk 'END print NR'
@Jidder 我认为 awk 有一些限制。
@Avinash Raj 在那里,我知道每条记录的 NF 和字符都有限制,但我从来没有遇到过 NR 的问题。我只是检查了一百万行文件并且它有效。不过,之前从未有过 5000 万条线路。
@Kent。该文件是在 MD(分子动力学)模拟期间创建的。我几乎可以确定文件没有问题。
【参考方案1】:
任何认真考虑速度线计数的人都可以创建自己的实现:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#define BUFFER_SIZE (1024 * 16)
char BUFFER[BUFFER_SIZE];
int main(int argc, char** argv)
unsigned int lines = 0;
int fd, r;
if (argc > 1)
char* file = argv[1];
if ((fd = open(file, O_RDONLY)) == -1)
fprintf(stderr, "Unable to open file \"%s\".\n", file);
return 1;
else
fd = fileno(stdin);
while ((r = read(fd, BUFFER, BUFFER_SIZE)) > 0)
char* p = BUFFER;
while ((p = memchr(p, '\n', (BUFFER + r) - p)))
++p;
++lines;
close(fd);
if (r == -1)
fprintf(stderr, "Read error.\n");
return 1;
printf("%d\n", lines);
return 0;
用法
a < input
... | a
a file
例子:
# time ./wc temp.txt
10000000
real 0m0.115s
user 0m0.102s
sys 0m0.014s
# time wc -l temp.txt
10000000 temp.txt
real 0m0.120s
user 0m0.103s
sys 0m0.016s
* 使用 GCC 4.8.2 在具有 AVX 和 SSE4.2 的系统上本机使用 -O3
编译的代码。
【讨论】:
【参考方案2】:你可以试试sed
sed -n '$=' file
=
表示打印行号,而美元表示只在最后一行打印。 -n
表示不要做太多其他事情。
或者这是 Perl 中的一种方法,将其保存为 wc.pl
并执行 chmod +x wc.pl
:
#!/usr/bin/perl
use strict;
use warnings;
my $filename = <@ARGV>;
my $lines = 0;
my $buffer;
open(FILE, $filename) or die "ERROR: Can not open file: $!";
while (sysread FILE, $buffer, 65536)
$lines += ($buffer =~ tr/\n//);
close FILE;
print "$lines\n";
像这样运行它:
wc.pl yourfile
基本上,它一次读取 64kB 的文件块,然后利用 tr
在要求它删除所有换行符后返回它所做的替换次数这一事实。
【讨论】:
我知道这听起来很奇怪,但是使用这个命令我根本没有输出。我尝试了一个非常小的文件(7 行),它可以工作。 我也尝试过 Perl,请再看看。【参考方案3】:尝试使用 nl 看看会发生什么......
【讨论】:
【参考方案4】:您可以使用awk
获取行数,如下所示
awk 'END print NR' names.txt
(或)使用while .. do .. done
bash 循环结构,如
CNT=0; while read -r LINE; do (( CNT++ )); done < names.txt; echo $CNT
【讨论】:
【参考方案5】:取决于您打开文件的方式,但可能从 STDIN 读取它会得到修复:
wc -l < file
【讨论】:
以上是关于比 wc -l 更快、更精确地计算行数的方法的主要内容,如果未能解决你的问题,请参考以下文章