晚上好!我需要你的帮助:)我这里有这种文本文件
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
使用2xawk
和sort
:cut
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-
awk
:打印序列字段的长度、行号和原始行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
awk
:将不应删除的记录添加到数组中lines
。对于每个记录,循环遍历已添加的数组条目并进行测试- 如果物种名称相同 (
$3 == tmp[3]
) - 如果序列较短 (
$1 < tmp[1]
) - 如果序列是子串 (
index(tmp[4], $4)
)
如果三个条件都为真,则跳到该
next
记录,否则将当前记录添加到数组中。打印块中的数组元素end
。- 如果物种名称相同 (
sort
:按原始行号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.*
唯一的匹配项。