我有一个这样的文件
>chr1
ACGTGGC
TGCCGTT
ATCCTTG
>chr2
ACTTTTA
CTCATAA
我想将 seq 转换为 1 个字符串。这应该是输出:
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
我该如何使用 awk 来做到这一点。我知道如何用 Perl 做到这一点。
谢谢
答案1
这应该按预期工作:
awk '/>chr/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' file
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
答案2
awk 'BEGIN{ RS=">[^\n]+\n"; }
NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }
{ rt=RT; }' myfile
输出:
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
作为一般参考:使用来自的输入数据FASTA 格式示例,并重复它以制作81.1MB测试文件,我得到以下time
结果:
Peter.O real 0m1.653s user 0m1.396s sys 0m0.256s
user2196728 real 0m6.587s user 0m5.972s sys 0m0.252s
kos real 0m12.866s user 0m12.589s sys 0m0.268s
所有测试方法的结果md5sum
都是相同的。
user2196728
的版本需要更改>chr
为只是>
为了更普遍地工作。
答案3
由于您使用的是非常特定的文件格式,因此我假设第一条记录始终采用以下形式><string>
:
< inputfile awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END {print x}' > outputfile
扩展:
NR==1 {
print;
next
}
!/>/ {
x=x$0;
next
}
/>/ {
print x"\n"$0;
x="";
next
}
END {
print x
}
- 仅当当前处理的记录号为 1 时才执行第一个块:它打印当前处理的记录并跳到下一条记录;
- 仅当正则表达式与当前处理的记录不匹配时才执行第二个块
>
:它将当前处理的记录的内容连接到变量x
并跳到下一条记录; - 仅当正则表达式与当前处理的记录匹配时才执行第三个块
>
:它打印变量的内容x
,后跟换行符,后跟当前处理的记录的内容,并跳到下一条记录; - 仅当没有更多记录需要处理时才执行第四块:它打印变量的内容
x
;
我对这个问题的所有答案进行了基准测试,md5sum
在系统启动后和发出命令后立即检查 SSD 上的输出文件sudo fstrim -v /
,使用以下bash
脚本,其中outputfile
通过重复以下位置的文件创建了一个约 226MB 的文件:这个链接10万次:
#!/bin/bash
for ((i=0; i<3; i++)); do /usr/bin/time -f "kos\t\treal %e" awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END{print x}' outputfile > outputfile1; done
for ((i=0; i<3; i++)); do /usr/bin/time -f "Peter.O\t\treal %e" awk 'BEGIN{ RS=">[^\n]+\n"; }NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }{ rt=RT; }' outputfile > outputfile2; done
for ((i=0; i<3; i++)); do /usr/bin/time -f "user2196728\treal %e" awk '/>/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' outputfile > outputfile3; done
md5sum outputfile1 outputfile2 outputfile3
这些是结果:
~$ sudo fstrim -v /
[sudo] password for user:
/: 68,8 GiB (73839202304 bytes) trimmed
~$ cd tmp
~/tmp$ bash exe
kos real 2.55
kos real 2.57
kos real 2.55
Peter.O real 2.93
Peter.O real 2.92
Peter.O real 2.92
user2196728 real 2.51
user2196728 real 2.51
user2196728 real 2.68
0618a8077b43eb44eb263d7d6f84777f outputfile1
0618a8077b43eb44eb263d7d6f84777f outputfile2
0618a8077b43eb44eb263d7d6f84777f outputfile3