【问题标题】:Count repeated columns of a line, print all lines and their count计算一行的重复列,打印所有行及其计数
【发布时间】:2019-12-08 21:55:55
【问题描述】:

我想要:

$ cat file
ABCDEFG, XXX
ABCDEFG, YYY
ABCDEFG, ZZZ
AAAAAAA, XZY
BBBBBBB, XYZ
CCCCCCC, YXZ
DDDDDDD, YZX
CDEFGHI, ZYX
CDEFGHI, XZY

$ cat file | magic
3 ABCDEFG, XXX
3 ABCDEFG, YYY
3 ABCDEFG, ZZZ
1 AAAAAAA, XZY
1 BBBBBBB, XYZ
1 CCCCCCC, YXZ
1 DDDDDDD, YZX
2 CDEFGHI, ZYX
2 CDEFGHI, XZY

因此,预排序的文件进入,识别第一列中的重复,计算此重复的行数,打印重复计数加上所有重复的行及其内容,包括第 2 列中的任何内容,这可以是任何东西,与唯一计数无关。 两个问题:

1) 得到uniq -c的效果,但不删除重复项。

我在网上搜索后真正“hacky”sed -e 的解决方案是这样的:

cat file | cut -d',' -f1 | uniq -c | sed -E -e 's/([0-9][0-9]*) (.*)/echo $(yes \1 \2 | head -\1)/;e' | sed -E 's/ ([0-9])/;\1/g' | tr ';' '\n'

我很惊讶地看到 head -\1 这样的东西可以正常工作,但很好。但是,我觉得应该有一个更简单的解决方案。

2) 上面去掉了第二列。我可以先运行我的代码,然后将 paste 运行到原始文件中的第二列,但文件很大,我希望尽可能提高速度。

有什么建议吗?

【问题讨论】:

    标签: bash awk sed large-files uniq


    【解决方案1】:

    一个在awk。很累,所以没有完全测试。我希望它有效,晚安:

    $ awk -F, '
    $1!=p {
        for(i=1;i<c;i++)
            print c-1,a[i]
        c=1
    }
    {
        a[c++]=$0
        p=$1
    }
    END {
        for(i=1;i<c;i++)
            print c-1,a[i]
    }' file
    

    输出:

    3 ABCDEFG,XXX
    3 ABCDEFG,YYY
    3 ABCDEFG,ZZZ
    1 AAAAAAA,XZY
    1 BBBBBBB,XYZ
    1 CCCCCCC,YXZ
    1 DDDDDDD,YZX
    2 CDEFGHI,ZYX
    2 CDEFGHI,XZY
    

    【讨论】:

    • 它适用于示例,但我犯了一个错误,我的文件实际上在逗号后不包含空格,这使您的解决方案失败。我对 awk 完全一无所知,如果您为我提供更正以处理丢失的空间,我将对您的解决方案进行基准测试
    • @Max 我有点修好了。这个在内存效率和性能方面比公认的要好得多
    • 修正后的版本适用于我没有空格的文件,并且比 Steve 的解决方案快两倍。一个 10gb 的文件大约需要 5 分钟
    • @Max 比只处理一次文件快一倍。
    • @oguzismail:这不取决于第一列中重复的数量吗?例如,如果第一个字段中的单个值占文件中值的 80%,则此解决方案会将 80% 的文件存储在内存中。不幸的是,我不认为使用这种方法可以摆脱这种情况。
    【解决方案2】:

    这是使用 的一种方法,它可以将文件传递两次。在第一次通过时,使用关联数组来存储第一列的计数。在第二遍中,打印数组值和行本身:

    awk -F, 'FNR==NR { a[$1]++; next } { print a[$1], $0 }' file{,}
    

    结果:

    3 ABCDEFG, XXX
    3 ABCDEFG, YYY
    3 ABCDEFG, ZZZ
    1 AAAAAAA, XZY
    1 BBBBBBB, XYZ
    1 CCCCCCC, YXZ
    1 DDDDDDD, YZX
    2 CDEFGHI, ZYX
    2 CDEFGHI, XZY
    

    【讨论】:

    • 这可行,但花费的时间大约是 James Brown 解决方案的两倍。对于一个 10gb 的文件,无论如何
    • @Max:不用担心——它会更慢,因为它读取输入文件两次。一个优点是它不需要排序输入。我不清楚您是否需要或想要排序输出。
    • @Max:就内存使用而言,它也更具可预测性。请看我上面的 cmets。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 2021-10-11
    相关资源
    最近更新 更多