如何为zgrep的每个匹配模式单独限制结果数而非全局限制?
给每个匹配模式单独限制结果数量的解决办法
你遇到的问题是zgrep的-m选项是全局统计匹配总数,不是给每个模式单独设置上限。这里给你几个实用方案,按效率从高到低排序:
方案1:用awk+zcat高效处理(首推)
awk能轻松实现按模式单独计数,达到指定次数后就不再处理该模式,而且只需要遍历一次压缩文件,1000个模式也能快速跑起来。命令如下:
zcat /projects/incoming/SRR80527_2.gz | awk -v max=10 ' BEGIN { # 先把所有模式读进数组,初始化每个模式的匹配计数为0 while ((getline pat < "/projects/test.indx") > 0) { patterns[pat] = 0 } close("/projects/test.indx") } { # 逐行检查每个未达上限的模式 for (p in patterns) { if (match($0, p)) { # 输出匹配到的内容(对应zgrep的-o) print substr($0, RSTART, RLENGTH) patterns[p]++ # 达到上限就删掉这个模式,后续不再检查 if (patterns[p] >= max) { delete patterns[p] } # 如果一行可能匹配多个模式,想都处理就删掉下面的break break } } # 所有模式都达标了就直接退出,不用继续读文件 if (length(patterns) == 0) exit }'
max=10就是每个模式要限制的匹配数,改数字就行- 如果你的模式是精确匹配(不是正则),把
match($0, p)改成$0 == p更准确 - 这个方案比循环1000次grep快太多,毕竟只读一次压缩文件
方案2:循环每个模式单独执行zgrep(简单但低效)
如果图省事,也可以遍历模式文件里的每一行,单独跑zgrep -m10。但这样要执行1000次zgrep,每次都得重新打开压缩文件,大文件的话会很慢,适合模式少的情况:
while read -r pat; do zgrep -o -m10 "$pat" /projects/incoming/SRR80527_2.gz done < /projects/test.indx
方案3:用pcregrep+awk(适合PCRE正则场景)
如果你的系统装了pcregrep,也可以用这个方法,但要注意如果同一个内容被多个模式匹配,计数会混在一起,不如方案1精准:
zcat /projects/incoming/SRR80527_2.gz | pcregrep -o -f /projects/test.indx | awk -v max=10 '{cnt[$0]++} cnt[$0] <= max'
内容的提问来源于stack exchange,提问作者Ahdee
相关产品推荐
相关产品推荐

