bash下快速修改多列取值相同的行的指定字段的方法
解决方案
你可以直接用awk两次扫描文件实现需求,全程只需要读取两次文件,不需要循环多次IO,处理10000+行的文件几乎是瞬间完成:
基础版命令(适配空白分隔的文件)
awk 'NR==FNR { cnt[$1,$4,$5]++ next } cnt[$1,$4,$5] >= 2 { $2 = 0 } 1' input.txt input.txt
逻辑说明
- 第一次读取文件时(
NR==FNR判断成立,NR是全局行号,FNR是当前文件的行号,首次读取时二者相等),以第1、4、5列的组合为键统计出现次数,统计完成后直接跳过后续逻辑处理下一行。 - 第二次读取文件时,判断当前行的1、4、5列组合的出现次数是否≥2,是的话将第2列赋值为0。
- 末尾的
1是awk的固定写法,作用是打印所有处理后的行。
格式保留版(适配制表符分隔/需要严格保留原有列间隔的场景)
如果你的文件是制表符分隔,需要保留输出的列格式,加上OFS(输出字段分隔符)设置即可:
awk 'BEGIN{OFS="\t"} NR==FNR{cnt[$1,$4,$5]++;next} cnt[$1,$4,$5]>=2{$2=0}1' input.txt input.txt
Perl单行实现
如果你更习惯用perl,也可以用下面的单行脚本实现相同逻辑:
perl -ane 'if ($. == $ARGC) { $k = join "\0", $F[0], $F[3], $F[4]; $F[1] = 0 if $cnt{$k} >=2; print join "\t", @F, "\n"; } else { $k = join "\0", $F[0], $F[3], $F[4]; $cnt{$k}++; }' input.txt input.txt
说明
perl的-a参数会自动将每行按空白分割到@F数组中,数组下标从0开始,所以第1列对应$F[0]、第4列对应$F[3]、第5列对应$F[4],逻辑和awk版本完全一致。
内容的提问来源于stack exchange,提问作者matheusb
相关产品推荐
相关产品推荐

