Perl文本處理
前幾天有個(gè)同事請(qǐng)教我安裝R的事,然后我甩給他一個(gè)R包讓他自己去安裝。最后因?yàn)榉?wù)器權(quán)限不足,沒(méi)有安裝成功。然后我問(wèn)了一下是需要什么功能,原來(lái)是需要將幾個(gè)文件整合到一起,我一想,這個(gè)perl不就可以解決了。接下來(lái)我要安利一下perl強(qiáng)大的文本處理能力了。
首先,假設(shè)我有很多個(gè)文件,格式如下:
現(xiàn)在我需要整合這幾個(gè)文件,最終格式如下:
0和1分別表示在對(duì)應(yīng)文件中存在與否(當(dāng)然也可以是對(duì)應(yīng)文件中的表達(dá)值)。
大家第一時(shí)間肯定會(huì)想到用哈希表,但是怎么用呢?每個(gè)文件設(shè)置一個(gè)哈希?這個(gè)太傻了,而且如果文件很多,那可怎么辦….那么用數(shù)組,但是數(shù)組怎么區(qū)分每一行呢?說(shuō)到這里,可能大家都知道了,沒(méi)錯(cuò),用哈希數(shù)組。
大概思路是這樣的,每當(dāng)?shù)趇個(gè)文件的某一行時(shí),檢測(cè)是否有name對(duì)應(yīng)的哈希key,如果沒(méi)有,設(shè)置以這個(gè)name為哈希key的哈希數(shù)組為0數(shù)組。然后將這個(gè)數(shù)組的第i個(gè)值設(shè)置為1就好了。
閑話少說(shuō),看代碼(注意加粗字體):
use warnings;
use strict;
my %hash=();
my @tmp=(0)x@ARGV;
for(my $i=0;$i<@ARGV;$i++){
open IN,$ARGV[$i];
while(){
chomp;
my @sArr=split(/\t/,$_);
unless(exists $hash{$sArr[0]}){
@{$hash{$sArr[0]}}=@tmp;
}
$hash{$sArr[0]}[$i]=1; }
close IN;
}
foreach my $key(keys %hash){
print join("\t",$key,@{$hash{$key}})."\n"; }
是不是很簡(jiǎn)單,所以一般涉及到文本處理我一般都是先用perl處理好,之后再用R進(jìn)行其它計(jì)算或者畫圖。
下面再安利一段添加千分符的程序,
use strict;
use warnings;
my $input =shift;
my $output=shift;
open IN,$input;
open OUT,">$output";
while(my $line=){
if($line=~s/(\d+.{0,1}\d+)/&separate($1)/eg);
print OUT $line;
}
sub separate{
my $number=$1;
if(substr($number,0,1)==0){return $number;}
if($number=~m/./){
return $number;
}
if(length($number)>3){
my $l=length($number);
my $i=int $l/3;
my $j=$l%3;
my $newnum="";
my $h=substr($number,0,$j);
for(;$i>0;$i--){
if($j!=0){$newnum=$newnum.$h.",";}
$h=substr($number,$j,3);
$j+=3;
}
$newnum=$newnum.$h;
return $newnum;
}
else{return $number;}
}
close(IN);
close(OUT);
這個(gè)代碼是我剛做生信的時(shí)候做的,思路也不難,首先通過(guò)這一段程序識(shí)別數(shù)字序列(純數(shù)字或帶小數(shù)點(diǎn)),然后對(duì)是別人到的數(shù)字系列進(jìn)行處理(也就是添加千分符),先得到數(shù)字系列長(zhǎng)度對(duì)3取模(字符處理位置)和取余數(shù)(循環(huán)次數(shù)),最后就是在循環(huán)里面用substr把千分符加進(jìn)去而已,思路很簡(jiǎn)單,具體還是看代碼吧。
perl強(qiáng)大的模式匹配以及好用的哈希結(jié)構(gòu),是很好的數(shù)據(jù)處理語(yǔ)言,特別是生信分析中涉及到的大量的匹配和數(shù)據(jù)提取整合等工作。