【问题标题】:Faster and precise way to count lines other than wc -l比 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(分子动力学)模拟期间创建的。我几乎可以确定文件没有问题。

标签: linux bash count lines wc


【解决方案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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-05-25
          • 2018-09-13
          • 1970-01-01
          • 2016-05-24
          • 1970-01-01
          • 2018-05-01
          • 1970-01-01
          相关资源
          最近更新 更多