首页 > 解决方案 > sed 第二次出现字符串 - 用于外部文件中的所有行 (Linux)

问题描述

我有一个文件在第 2 列中有重复值,需要重命名。在整个 ~5m 行文件(with.duplicates )中有 ~8k 重复值(在文件list.of.duplicates中)。

数据集输入:

with.duplicates

1 rs143225517 0 751756 CT

1 rs146277091 0 752478 AG

1 rs3094315 0 752566 遗传算法

1 rs149886465 0 752617 交流电

1 rs3131972 0 752721 AG

1 rs3131972 0 752721 AT G

1 rs3131971 0 752894 TC

1 rs61770173 0 753405 CA

1 rs2073814 0 753474 CG

1 rs2073813 0 753541 AG

1 rs12184325 0 754105 TC

重复列表

rs3131972

rs4310388

rs7529459

rs905135

rs9786995

rs12065710

rs6426404

rs12759849

rs6603823

我试过的代码

这正是我想要的——但效率低下,而且只有一次替换

sed -i '0,/rs3131972/! s/rs3131972/qrs3131972/' with.duplicates

但我不知道如何遍历整个重复值列表

i=0 
while ((i++)); 
read -r snp 
do 
sed -i '0,/${snp}/! s/${snp}/q${snp}/' with.duplicates 
done < list.of.duplicates

我在整个网站上找到了部分答案,但没有一个可以将所有内容整合到一个有效的脚本中。

提前感谢您的帮助!

在 Linux 或 R 中寻找解决方案

编辑:

期望的输出

1 rs143225517 0 751756 CT

1 rs146277091 0 752478 AG

1 rs3094315 0 752566 遗传算法

1 rs149886465 0 752617 交流电

1 rs3131972 0 752721 AG

1 qrs3131972 0 752721 AT G

1 rs3131971 0 752894 TC

1 rs61770173 0 753405 CA

1 rs2073814 0 753474 CG

1 rs2073813 0 753541 AG

1 rs12184325 0 754105 TC

标签: linuxsedwhile-loop

解决方案


好吧,awk 可以自己处理这个问题。你不需要循环。

awk '(FNR==NR) { d[$1]; next }
     ($2 in d) && !(++d[$2]-2) { $2 = "q" $2; delete a[$2] }
     1' list.of.duplicates with.duplicates

是否可以将其修改为不是将“q”添加到第二次出现的第二列,而是将 q 添加到较长行的第二列?

可以,但这不会像上面那样有效。

awk '(ARGIND==1) { d[$1]; next }
     (ARGIND==2) {
         if ($2 in d) {
             if ($2 in r) { if (length(r[$2]) > length()) d[$2]++; delete r[$2] }
             else { r[$2] = $0 }
         } next }
     ($2 in d) && !(++d[$2]-2) { $2 = "q" $2; delete d[$2] }
     1' list.of.duplicates with.duplicates with.duplicates

推荐阅读