如何删除与另一行相似但较短的行?

如何删除与另一行相似但较短的行?

晚上好!我需要你的帮助:)我这里有这种文本文件

Espece_A ACGT
Espece_B ACCT
Espece_B GACCTT
Espece_B ATCTGG
Espece_C ACCTG
Espece_D ACCT

每行包含一个物种名称 (Espece_X) 和一个相应的序列(例如 AACGT),以空格分隔。行根据第一个单词排序。

我的目标是删除与另一行相似但较短的行。我不知道该怎么做!

在此示例中,应删除第二行,因为它与第三行完全相同,但更短。

结果文件:

Espece_A ACGT
Espece_B GACCTT
Espece_B ATCTGG
Espece_C ACCTG
Espece_D ACCT

预先非常感谢你阿德里安

答案1

使用2xawksortcut

awk '{print length($2), NR, $0}' file |
  sort -k1,1nr |
  awk '
  {
    for(i=1;i<=cnt;i++){
      split(lines[i], tmp)
      if ($3 == tmp[3] && $1 < tmp[1] && index(tmp[4], $4)) next
    }
    lines[++cnt]=$0
  }
  END{
    for(i=1;i<=cnt;i++) print lines[i]
  }' |
  sort -k2,2n |
  cut -d' ' -f3-
  1. awk:打印序列字段的长度、行号和原始行

  2. sort:按照序列字段的长度进行反向排序,输出是这样的:

    6 3 Espece_B GACCTT
    6 4 Espece_B ATCTGG
    5 5 Espece_C ACCTG
    4 1 Espece_A ACGT
    4 2 Espece_B ACCT
    4 6 Espece_D ACCT
    
  3. awk:将不应删除的记录添加到数组中lines。对于每个记录,循环遍历已添加的数组条目并进行测试

    • 如果物种名称相同 ( $3 == tmp[3])
    • 如果序列较短 ( $1 < tmp[1])
    • 如果序列是子串 ( index(tmp[4], $4))

    如果三个条件都为真,则跳到该next记录,否则将当前记录添加到数组中。打印块中的数组元素end

  4. sort:按原始行号

  5. cut:删除前两个字段

答案2

一个简短的 Python 程序就可以完成此任务,并且可以轻松地在 Bash 中运行。

#!/usr/bin/env python3
import sys
last_line = ""
for line in sys.stdin:
    if len(line) > len(last_line) or line[0:-1] != last_line[0:len(line)-1]:
        print(line, end='')
    last_line = line

用法:

  • 将上面的代码复制到一个名为del_shorter.py
  • 使文件可执行:chmod +x del_shorter.py
  • 使用反向排序的文件作为输入运行它,并再次对输出进行排序:
cat your_file.txt |sort -r |./del_short_matches.py |sort

答案3

如果文件不太大,那么这里有一个大锤

while read s g; 
   do n=$(sed -nE "/"$s" .*"$g".*/p" file | wc -l); 
  [ $n -eq 1 ] && echo $s $g;  
done < file 

仅返回species .*gene.*唯一的匹配项。

相关内容