以下是我需要处理的文件格式:
@HWI-ST150_0129:2:1:4226:2616#0/1
CATCTTTTCTCTTAACTTCCATGATGGTACATCTTTTGATTTTTTTTTAATAACGTCTTTGACAGCTTAAATTCTTTTTCAAAATC
+HWI-ST150_0129:2:1:4226:2616#0/1
d\dddddaddbcad^\^a\]ZZZ_`]\VYa_bZ^_^\YX\X`eeeeffffffefffeeefffefffeeffBBBBBBBBBBBBBBBB
基本上我需要做的是: 1.每隔4行挑出一次;并修剪字符串END处所有可能的尾随“B”。
2.如果左侧部分是>修剪后整个弦的70%,然后:在第4行为第4行的“B”修剪对应物。
3.然后将所有4行追加第2和第4修剪。
所以预期的结果如下:
@HWI-ST150_0129:2:1:4226:2616#0/1
CATCTTTTCTCTTAACTTCCATGATGGTACATCTTTTGATTTTTTTTTAATAACGTCTTTGACAGCTTAA
+HWI-ST150_0129:2:1:4226:2616#0/1
d\dddddaddbcad^\^a\]ZZZ_`]\VYa_bZ^_^\YX\X`eeeeffffffefffeeefffefffeeff
我写了一个类似的脚本:
for((a=1;a<=8000000;a++))
do
if (($a%4==0))
then
b=`cat $FILENAME|head -$a|tail -1|sed 's/\(.\)B*$/\1/g'|wc -c`
d=`cat $FILENAME|head -$a|tail -1|wc -c`
if (( 10*$b/$d>= 7 ))
then
cat $FILENAME|head -$(($a-3))|tail -1
cat $FILENAME|head -$(($a-2))|tail -1|cut -b 1-$(($b-1))
cat $FILENAME|head -$(($a-1))|tail -1
cat $FILENAME|head -$a|tail -1|sed 's/\(.\)B*$/\1/g'
fi
fi
done >> /home/xxx/$DIRNAME/$FILENAME
我认为我更喜欢bash代码,因为它很快(?)。但是,当我运行此代码时,考虑8000000行时,它很慢。另外,也许我在代码中使用了“cat”太多了?
快速,我的意思是说,当使用split命令分割GB级大文件时;它超级超级快。 (分裂的机制是什么?)
有什么建议可以提高速度吗?
答案 0 :(得分:2)
改变你的逻辑,使它像这样工作:
1)读入4行。
2)处理你读过的4行。
3)写出处理结果
4)重复。
您的代码在每次传递时都会通过该文件六次。你只需要为所有事情完成一次。
答案 1 :(得分:1)
我认为问题的一部分可能是最外面的for循环的每次迭代,你将要抓住/标题/无论整个文本文件......我想这将是瓶颈的来源。
删除cat可能不会更快,因为你每次都在上面调用其他unix命令。
您可能希望寻找一种只能读取文件并生成必要输出的解决方案,而不是将其读取8,000,000 * 6次。 (1对48,000,000!:))
以下是这个想法:
f = OPEN_FILE() //Some file descriptor
out_f = NEW_FILE_FOR_WRITING() //open some file to write to
while not_eof(f):
cur_window = read_four_lines(f) //Get four lines from the text thing
modified_block = do_stuff(cur_window) //Do your processing in a different function
write(out_f,modified_block) //Write the modified stuff to the output file
我不确定你最喜欢哪种语言,但这不应该太难。我想象在bash脚本中可以进行一些修改。
答案 2 :(得分:0)
您可以使用~
对sed
的每一行进行更改。如果您打算修剪INPUT_FILE每四行的所有尾随B,那么只需执行 -
例如:
[jaypal:~/Temp] cat file
1
2
3
4
5
6
7
8
9
10
[jaypal:~/Temp] sed '0~4 s/[0-9]/bbbb/' file
1
2
3
bbbb
5
6
7
bbbb
9
10
答案 3 :(得分:0)
这是David在bash中提供的逻辑的简单实现,每个循环只有一个外部命令:
#!/bin/bash
DONE=false
until $DONE ; do
read -r LINE1 || DONE=true
read -r LINE2 || DONE=true
read -r LINE3 || DONE=true
read -r LINE4 || DONE=true
NEWLINE4=`echo $LINE4 |sed 's/\(.\)B*$/\1/g'`
NEWLINE2=${LINE2:0:${#NEWLINE4}}
echo $LINE1
echo $NEWLINE2
echo $LINE3
echo $NEWLINE4
done
这很简单,有一些问题(最后打印4条空行),很容易修复。此代码应该比第一个版本快许多倍。