我有以下具有30233088字符串的(大)文件:
head mystringfile.txt:
GAATGAACACGAAGAA
GAATGAACACGAAGAC
GAATGAACACGAAGAG
GAATGAACACGAAGCA
cat sequence.txt
AAATAGAGGGCGGTCCAGGCGTGTCGAAACACTGGGTCCAGGGCAAGAGCGGTTCGGGTGTCAGGAAAGCCCCCAAGGGGGTTCGCGCGGTTTGCAGTGAGGTAGAGGCCGGTGTATGGGTAGACAATTGGGGTCCCAAAGAAAAAGGCTCGTCCAACATCATAATAAACCCAAGCACGATAAAAAGCAAACGCAGACTTCAATAGGGTACGAGCAATTGTGGCAGGGTGCTCGCTGTCAGGGTTAGATCTTCTTGGAGTCGCGTCGCTCGGGGGGGCAAGGCCAACGTAAGATCGTGGCTGATCGCTGGCAATGCGGTCGGTTGGGTGGTCGCTAGTAGGGGCACGGCGGTCTCTTATGGCGTCGTAAAATGCGTCTCCAAAGCGAAAAGGGGCGGCAGACAAGTCACCGGGCAAGCTTAGAGGTCTGGGGCCCGTGGCTTTAGGGGAATGAACACGAAGACGCGAAACGAAGTCGTGTTTCTTGTTGGCTGTAGAGGGGAAAACCGTCTGGGGCGATCTGGCGTAGTAGTGCGTGTCTTGCAGTGAGCTCCCCGTCCGTAAGGATTCGCAGGAATCCTGCGTGAAGCTCGGTCGTCTCGGCCGTGTCTCGGGGTTTGATTGCGGGTTCAGATTGGAAAGGTCTCCTCGGGTCGTTTGCTGCATTTGCTCGCAACCCTGACGTGAAAGGGGTGAGCTGTCTCCAATCTGCCACGCTGGGTGTTGCGTCGTCAGTAAAAGACTTGGTCAAGCTGGGACCTCGCAAGATCGCGAGAGGGTTAAGCACAAAAGGTATGGCGAAGCTCCCGGGTGCTCTTGTGGCCACCCAGAATCATGGTGACGTAGGTTTTGCGAAGCCATCAAAAATTCAGGCGGCAAAACGAGCCAGTAGGGTCCTGGGCAGCTGGGCTTGTAGTGGGTAGGCGGCAAAACGCAAAGAATGAACACGAAGCAACTCCGTAGTGTGACGGGGGTTCTGACAAACGTCCTGCAAGAAGTTCGTCTTGGG
我需要在另一个序列文件中grep
来确定比赛的位置,具体操作如下:
while read line; do grep -b -o $line sequence.txt >>sequence.txt.count; done<mystringfile.txt
像这样运行代码当然会花费很长时间,并且只运行1个线程的一部分,那么如何修改它(使用parallel
或xargs
?)以便在上面运行我要指定多少个线程?
答案 0 :(得分:3)
使用shell循环处理文本,您的想法是错误的。您正在打开一个新的文件描述符,以针对输入文件上的30233088迭代中的每个迭代重定向到输出文件。这很可能会对性能产生巨大影响,或者容易导致打开的文件描述符用尽。
使用正确的工具进行作业。 Awk
是您的朋友在这里。如果您所说的sequence.txt
只是一个巨大的模式,则可以将其插入到正则表达式匹配的变量中,如下所示。该解决方案不涉及将条目存储在RAM中的内存开销
awk -v sequence="$(<sequence.txt)" 'n=index(sequence, $1){print n":"$1}' mystringfile.txt
这应该比您所采用的方法相对更快,并且为了进一步加快速度,请更改locale
设置以匹配C
本地
LC_ALL=C awk -v sequence="$(<sequence.txt)" 'n=index(sequence, $1){print n":"$1}' mystringfile.txt
要与grep
的{{1}}选项匹配以打印字节偏移开始,请在上面的答案中使用-b
而不是n-1
。
如果您仍要使用GNU并行,请使用n
将文件物理拆分为多个部分,并指定--pipepart
大小以读取多少MB的文件内容
--block
答案 1 :(得分:2)
如果您在 mystringfile.txt
中的所有搜索字符串都具有相同的长度(例如在示例文件中为16个字节),则可以存储所有16个字节从sequence.txt
到关联数组(如果有内存)的字符串,并加快了搜索速度。让我们尝试一下。首先,我们需要一些测试材料,让我们创建一个2400000字节的sequence.txt
,大约需要一秒钟:
$ awk -v seed=$RANDOM 'BEGIN{a[0]="A";a[1]="C";a[2]="G";a[3]="T";srand(seed);for(i=1;i<=2400000;i++)printf "%s", a[int(4*rand())];print ""}' > mystringfile.txt
和mystringfile.txt
和30233088 16字节搜索字符串(4分钟50秒):
$ awk -v seed=$RANDOM 'BEGIN{a[0]="A";a[1]="C";a[2]="G";a[3]="T";srand(seed);for(i=1;i<=30233088;i++){for(j=1;j<=16;j++)printf "%s", a[int(4*rand())];print ""}}' > mystringfile.txt
然后是脚本:
$ awk '
NR==FNR { # process the sequence file
l=length($1)-15 # length-15 16 byte strings coming up
for(i=1;i<=l;i++) { # using l as variable name is stupid
s=substr($0,i,16)
a[s]=a[s] (a[s]==""?"":",") i # hash string start indexes to a, string as key
} # a["ACTGTGCACGTATAGC"]=3,141,592
next
} # the search part
$1 in a { # if search string is found
print a[$1], $1 # output index and string
}' sequence.txt mystringfile.txt
将2400000字节的sequence.txt
存储到哈希中需要13秒,并且在我的微型笔记本电脑上使用了721 MB的内存。整个脚本运行了35秒,发现了约17000次点击。