我有一个字符序列的文本文件,该文件由两行组成:标题和下一行的序列本身。该文件的结构如下:
>header1
aaaaaaaaa
>header2
bbbbbbbbbbb
>header3
aaabbbaaaa
[...]
>headerN
aaabbaabaa
在另一个文件中,我有一个要删除的序列标头的列表,如下所示:
>header1
>header5
>header12
[...]
>header145
这个想法是从第一个文件中删除这些序列,因此所有这些标题和下一行。我使用sed进行了如下操作,
while read line; do sed -i "/$line/,+1d" first_file.txt; done < second_file.txt
它可以工作,但是要花很长时间,因为我用sed多次加载了整个文件,而且它很大。关于如何加快此过程的任何想法?
答案 0 :(得分:1)
$ awk 'NR==FNR{a[$0];next} $0 in a{c=2} !(c&&c--)' list file
>header2
bbbbbbbbbbb
>header3
aaabbbaaaa
[...]
>headerN
aaabbaabaa
c
是您要从刚匹配的那一行开始跳过的几行。参见https://stackoverflow.com/a/17914105/1745001。
或者:
$ awk 'NR==FNR{a[$0];next} /^>/{f=($0 in a ? 1 : 0)} !f' list file
>header2
bbbbbbbbbbb
>header3
aaabbbaaaa
[...]
>headerN
aaabbaabaa
f
是在目标数组>...
中是否找到最近读取的a[]
行。 f=($0 in a ? 1 : 0)
可以缩写为f=($0 in a)
,但为了清晰起见,我更喜欢三元表达式。
第一个脚本取决于您知道每个记录有多少行,而第二个脚本则取决于从>
开始的每个记录。如果两者都知道,那么选择哪种样式就可以。
答案 1 :(得分:1)
您可以使用此awk
:
awk 'NR == FNR{seen[$0]; next} /^>/{p = !($0 in seen)} p' hdr.txt details.txt
答案 2 :(得分:1)
您遇到的问题很容易回答,但是当您处理常规fasta文件时不会有帮助。 Fasta文件具有序列标头,后跟一行或多行,可以将其连接起来以表示序列。 Fasta文件格式大致遵循以下规则:
- 以
字符( >
开头的描述行(defline)或标头/标识符行,给出了序列的名称和/或唯一标识符,并且还可能包含其他内容信息。- 在描述行之后是标准的单字母字符串中的实际序列本身。除有效字符外的任何其他字符(包括空格,制表符,星号等)都将被忽略。
- 序列可以跨越多行。
- 通常通过在两个后续序列之间留空行来将多个单个序列FASTA文件连接到一个公共文件中,从而获得多序列FASTA格式。
大多数提出的方法将在具有多行序列的多fasta上失败
以下内容将始终有效:
awk '(NR==FNR) { toRemove[$1]; next }
/^>/ { p=1; for(h in toRemove) if ( h ~ $0) p=0 }
p' headers.txt file.fasta
这与EdMorton和Anubahuva的答案非常相似,但是这里的区别在于文件headers.txt
只能包含标头的一部分。
答案 3 :(得分:0)
一种选择是创建一个长sed表达式:
sedcmd=
while read line; do sedcmd+="/^$line\$/,+1d;"; done < second_file.txt
echo "sedcmd:$sedcmd"
sed $sedcmd first_file.txt
这将只读取一次文件。请注意,我在sed模式中添加了^
和$
(因此>header1
与>header123
不匹配...)
如果您有成千上万个文件,则使用文件(如@daniu所建议的)可能会更好,因为使用此方法可能会导致达到命令行最大计数。
答案 4 :(得分:0)
使用第二个文件中的删除命令创建脚本:
void clear()
然后将该文件应用于第一个
sed 's#\(.*\)#/\1/,+1d#' secondFile.txt > commands.sed
答案 5 :(得分:0)
此awk
可能对您有用:
awk 'FNR==NR{a[$0]=1;next}a[$0]{getline;next}1' input2 input1
答案 6 :(得分:0)
尝试gnu sed,
sed -E ':s $!N;s/\n/\|/;ts ;s~.*~/&/\{N;d\}~' second_file.txt| sed -E -f - first_file.txt
在两个脚本前附加time
命令以比较速度,
看起来time while read line;do...
和time sed -....
的结果在我的测试中完成了,不到OP的一半时间