Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash:uniq计数大型数据集_Bash_Uniq - Fatal编程技术网

Bash:uniq计数大型数据集

Bash:uniq计数大型数据集,bash,uniq,Bash,Uniq,我有一组跨越70GB的CVS文件,其中35GB是我感兴趣的字段(每行中这个字段大约有100字节) 数据是高度重复的(抽样显示前1000行覆盖了50%以上的行),我对获取uniq总计数感兴趣 如果数据集不太大,我会这样做 cat my.csv | cut-f5 | sort | uniq-c | sort--numeric它工作正常 然而,我的问题是(据我所知)由于中间的排序,该命令需要在RAM中保存(然后在磁盘上保存,因为它不适合我的16Go RAM)整个数据集,然后将其流到uniq-c 我想知

我有一组跨越70GB的CVS文件,其中35GB是我感兴趣的字段(每行中这个字段大约有100字节)

数据是高度重复的(抽样显示前1000行覆盖了50%以上的行),我对获取uniq总计数感兴趣

如果数据集不太大,我会这样做

cat my.csv | cut-f5 | sort | uniq-c | sort--numeric
它工作正常

然而,我的问题是(据我所知)由于中间的
排序
,该命令需要在RAM中保存(然后在磁盘上保存,因为它不适合我的16Go RAM)整个数据集,然后将其流到
uniq-c

我想知道是否有一个命令/脚本awk/python可以一步完成
排序| uniq-c
,从而使RAM消耗低得多?

您可以尝试以下方法:

perl -F, -MDigest::MD5=md5 -lanE 'say unless $seen{ md5($F[4]) }++' < file.csv >unique_field5.txt
split --filter='sort | uniq -c | sed "s/^\s*//" > $FILE' -b 15G -d "dataset" "dataset-"
为了同样的结果

当然,md5现在在加密方面并不安全,但可能足以进行排序。。。当然,可以使用
sha1
sha256
,只需使用
-MDigest::SHA=sha255
。当然,sha摘要较长,例如需要更多内存

它类似于注释中链接的
awk
,不同的是,这里用作哈希键的不是整个输入行,而是长MD5摘要的
16字节

编辑 因为我对性能感到好奇,所以创建了以下测试用例:

# this perl create 400,000,000 records
# each 100 bytes + attached random number,
# total size of data 40GB.
# each invocation generates same data (srand(1))
# because the random number is between 0 - 50_000_000
#    here is approx. 25% unique records.
gendata() {
perl -E '
    BEGIN{ srand(1) }
    say "x"x100, int(rand()*50_000_000) for 1..400_000_000
'
}

# the unique sorting - by digest
# also using Devel::Size perl module to get the final size of the data hold in the memory

# using md5
domd5() {
    perl -MDigest::MD5=md5 -MDevel::Size=total_size -lnE '
        say unless $seen{md5($_)}++;
        END {
            warn"total: " . total_size(\%seen);
        }'
}
#using sha256
dosha256() {
    perl -MDigest::SHA=sha256 -MDevel::Size=total_size -lnE '
        say unless $seen{sha256($_)}++;
        END {
            warn"total: " . total_size(\%seen);
        }'
}

#MAIN
time gendata | domd5    | wc -l 
time gendata | dosha256 | wc -l 
结果:

total: 5435239618 at -e line 4, <> line 400000000.
 49983353

real    10m12,689s
user    12m43,714s
sys 0m29,069s
total: 6234973266 at -e line 4, <> line 400000000.
 49983353

real    15m51,884s
user    18m23,900s
sys 0m29,485s
e、 g运行:

time gendata | doplain | wc -l
结果:

  • 内存使用量要大得多:1002260682-我的16GB内存笔记本开始大量交换(因为有SSD,所以没什么大不了的-但仍然…)
  • 独特记录:49983353
  • 运行时间:8:30分钟
结果如何

只要使用

cut -d, -f5 csv | perl -MDigest::MD5=md5 -lnE 'say unless $seen{md5($_)}++'
而且你应该足够快地获得独特的线条。

你可以尝试以下方法:

perl -F, -MDigest::MD5=md5 -lanE 'say unless $seen{ md5($F[4]) }++' < file.csv >unique_field5.txt
split --filter='sort | uniq -c | sed "s/^\s*//" > $FILE' -b 15G -d "dataset" "dataset-"
此时,您应该有大约5个
数据集-
,每个数据集都应该比
15G
小得多

要合并文件,可以将以下bash脚本另存为
merge.bash

#! /bin/bash
#

read prev_line
prev_count=${prev_line%% *}

while read line; do
    count="${line%% *}"
    line="${line#* }" # This line does not handle blank lines correctly
    if [ "$line" != "$prev_line" ]; then
        echo "$prev_count $prev_line"
        prev_count=$count
        prev_line=$line
    else
        prev_count=$((prev_count + count))
    fi
done

echo "$prev_count $prev_line"
并运行以下命令:

sort -m -k 2 dataset-* | bash merge.sh > final_dataset.

注意:空行处理不正确,如果它符合您的需要,您可以将其从数据集中删除或更正
合并。bash

没有对其进行测试,但假装可以使用
awk
@jm666。据我所知,它包含整行的哈希,这将降低内存消耗。如果即使是唯一行的散列数组也无法保存在内存中,则必须使用另一种方法。您有足够的存储空间来创建数据集的副本吗?@jm666 My bad应该阅读更广泛的内容。作者确实使用了
散列
作为我所知道的
关联数组
@jm666,我偶尔会运行它一次,所以速度是值得赞赏的,但不是必需的,更重要的是我有一个100Go磁盘和16RAM,目前命令正在完成,因为sort在RAM和磁盘中都耗尽了空间。@siel我正在运行您的解决方案,我很快就能告诉你它是否有效,以及它在性能方面可以使用多少次。你甚至可以使用非加密散列,例如,它是并行运行还是顺序运行?你必须检查
split
的文档,但我认为合并部分是不可并行的。这与map/reduce范例非常相似。