2012-12-26 2 views
2

세계의 Perl 마스터에게!Perl 데이터 구문 분석 및 삽입 라인

나는 위치, 끝 위치와 방향을 시작, 첫 번째 열, ID, 엑손 정보부터 분석하고 만들고 싶어이 같은 파일 ......

있습니다. ID가 숫자를 만났을 때 ID가 1 씩 증가합니다. 이 같은

1 9239 712 8571 + 
1 start_codon 712 714 + 
1 stop_codon 8569 8571 + 
2 3882 24137 24264 + 
2 start_codon 24137 24139 + 
3 3882 24322 24391 + 
4 3882 24490 26064 + 
4 stop_codon 26062 26064 + 
5 4972 26704 26740 + 
5 start_codon 26704 26706 + 
6 4972 26814 27170 + 
7 4972 27257 27978 + 
7 stop_codon 27976 27978 + 
8 10048 40161 41114 - 
8 start_codon 41112 41114 - 
8 stop_codon 40161 40163 - 
9 272 43167 43629 - 
9 stop_codon 43167 43169 - 
10 272 43755 44059 - 
10 start_codon 44057 44059 - 

....

1 9239 *712* *8571* + 
1 start_codon 712 714 + 
1 stop_codon 8569 8571 + 
*X 9239 712 8571 +* 
2 3882 *24137* 24264 + 
2 start_codon 24137 24139 + 
3 3882 24322 24391 + 
4 3882 24490 *26064* + 
4 stop_codon 26062 26064 + 
*X 3882 24173 26064 +* 
5 4972 *26704* 26740 + 
5 start_codon 26704 26706 + 
6 4972 26814 27170 + 
7 4972 27257 *27978* + 
7 stop_codon 27976 27978 + 
*X 4972 26704 27978 +* 
8 10048 *40161* *41114* - 
8 start_codon 41112 41114 - 
8 stop_codon 40161 40163 - 
*X 10048 40161 41114 -* 
9 272 *43167* 43629 - 
9 stop_codon 43167 43169 - 
10 272 43755 *44059* - 
10 start_codon 44057 44059 - 
*X 272 43167 44059 -* 

각 라인은 X로 시작 추가되어야하지만 난 할 수 없습니다 내 기술 ...와 :(

것은 모든 엑손입니다 "start_codon"과 "end_codon"을 무시한 두 번째 열의 숫자는 별표 사이의 최소 엑손 위치와 최대 엑손 위치를 가져와야합니다 *.

이것은 t를 구문 분석하는 기본 코드입니다 그는 데이터 ...하지만 처음부터 다시 코드 (줄 'X'를 삽입하는 방법을 전혀 모르겠다)

(미안 해요 코드를 그렇게 좋지 않아서 삭제했습니다. 혼란을 줄 수 있습니다 ...)

세계의 주인공, 저를 도와주세요. ???

감사합니다.

AS TLP aked 나는 코드를 다시 작성했다. 여기 하나의 방법, 바로 당신을 이해한다면 어떻게 내가 가장 큰 값과 가장 낮은 값을 비교할 수 있습니다

use strict; 

if (@ARGV != 1) { 
    print "Invalid arguments\n"; 
    print "Usage: perl min_max.pl [exon_output_file]\n"; 
    exit(0); 
} 

my $FILENAME = $ARGV[0]; 
    my $exonid = 0; 
    my $exon = ""; 
    my $startpos = 0; 
    my $endpos = 0; 
    my $strand = ""; 
    my $min_pos = 0; 
    my $max_pos = 0; 

open (DATA, $FILENAME); 

while (my $line = <DATA>) { 
    chomp $line; 

    if ($line ne "") { 
     if ($line =~ /^(.+)\t(.+)\t(.+)\t(.+)\t(.+)/) { 
     $exonid = $1; 
     $exon = $2; 
     $startpos = $3; 
     $endpos = $4; 
     $strand = $5; 
     } 
     if ($exon =~ /\d+/) { 
      print $exonid,"\t",$exon,"\t",$startpos,"\t",$endpos,"\t",$strand,"\n"; 
     } else { 
      print $exonid,"\t",$exon,"\t",$startpos,"\t",$endpos,"\t",$strand,"\n"; 
     } 
    } 
} 

close (DATA); 
exit; 

불구하고 그것의 당황 코드 ....

+0

합니다. 그게 어떻게 가능할 수 있니? – TLP

+0

정확하게, 나는 노력하고 있었다. 그러나 나는 시작할 수없는 가장 기본적인 코드를 넣었다. 그래서 나는 작동하지 않는 모든 부분을 삭제했다. 나는 아직도 일하고있다. 그 이유는 위의 코드가 너무 간단합니다. 고맙습니다. : – Karyo

+0

왜'* X 10048 40161 41114 - *'not'* X 10048 41112 41114 - *'8? –

답변

3

기본적으로 원하는 것은 행을 통과하고 싶지 않은 행을 건너 뛰고 (즉, 2 번 열에 숫자 없음), 동일한 세트의 각 새 행에 대해 최소/최대를 기억하고, col 2 번호 변경 사항을 인쇄하고 다시 시작합니다. 이 솔루션을 사용하면 맨 마지막에 수동으로 마지막 세트를 인쇄해야합니다.

이 코드는 데모 데이터로 내부 파일 DATA을 사용합니다. 간단히과 같이 대상 입력 파일에서 사용할 <><DATA>을 변경 perl script.pl inputfile

use strict; 
use warnings; 
use List::Util qw(min max); 

my $print; 
my ($min, $max, $id); 
while (<DATA>) {     ###### change to <> to run on input file 
    my @line = split; 
    if ($line[1] !~ /^\d+$/) {    # if non-numbers in col 2 
     print;        # print line 
     next;        # skip to next line 
    } 
    if (!defined($id) or $id != $line[1]) { # New dataset! 
     say $print if $print;     # Print and reset 
     $id = $line[1]; 
     $min = $max = undef; 
    } 
    $min = min($min //(), @line[2,3]);  # find min/max, skip undef 
    $max = max($max //(), @line[2,3]); 
    $print = join "\t", "X", $line[1], $min, $max; # buffer the print 
} 
print $print; 

__DATA__ 
1 9239 712 8571 + 
1 start_codon 712 714 + 
1 stop_codon 8569 8571 + 
2 3882 24137 24264 + 
2 start_codon 24137 24139 + 
3 3882 24322 24391 + 
4 3882 24490 26064 + 
4 stop_codon 26062 26064 + 
5 4972 26704 26740 + 
5 start_codon 26704 26706 + 
6 4972 26814 27170 + 
7 4972 27257 27978 + 
7 stop_codon 27976 27978 + 
8 10048 40161 41114 - 
8 start_codon 41112 41114 - 
8 stop_codon 40161 40163 - 
9 272 43167 43629 - 
9 stop_codon 43167 43169 - 
10 272 43755 44059 - 
10 start_codon 44057 44059 - 

출력 : 당신은 어디 최소/최대 값을 저장 할 시도를하지 않은

9239 712  8571 
3882 24137 26064 
4972 26704 27978 
10048 40161 41114 
272  43167 44059 
+0

Thanx TLP가 도움이되었지만 원하는 출력은 내 질문에 두 번째 상자와 같았습니다. 하지만 코드를 읽으면 펄을 더 배우는 데 도움이 될 것입니다. 그래서 기쁩니다. 그리고 당신의 도움과 시간에 감사드립니다. – Karyo

+0

@Karyo 이는'next' 문 앞에'print' 문을 추가 한 다음'$ print' 변수를 다시 포맷하는 것입니다. 당신이 min/max 숫자 주위에'*'기호를 원한다면 말입니다. – TLP

+0

감사합니다. TLP를 사용하면 더 일반적으로 작동합니다. !!!! 다음 문장 이전에 print 문을 추가하면 무슨 뜻입니까? 죄송합니다. 알겠습니다 :( – Karyo

2

(테스트되지 않은이!) 당신이 될 것 같다 일을하는 요청 : 기본적으로

use strict; 
use warnings; 
use feature 'say'; 

# read first line, initialize accumulators, print it back 
chomp($_ = <>); 
my ($last_id, $last_exon, $min_start, $max_end, $last_strand) = split /\t/; 
say $_; 

# loop over remaining lines 
while (<>) { 
    chomp; 
    my ($exonid, $exon, $startpos, $endpos, $strand) = split /\t/; 

    if ($exon !~ /\D/ and $exon != $last_exon) { 
     # new exon found, print summary of last one... 
     say join "\t", "X", $last_exon, $min_start, $max_end, $last_strand; 
     # ...and reset accumulators 
     ($last_id, $last_exon, $min_start, $max_end, $last_strand) 
      = ($exonid, $exon, $startpos, $endpos, $strand); 
    } 
    else { 
     # previous exon continues, just update accumulators 
     $last_id  = $exonid; 
     $last_exon = $exon  if $exon !~ /\D/; 
     $min_start = $startpos if $min_start > $startpos; 
     $max_end  = $endpos if $max_end < $endpos; 
     $last_strand = $strand; # should not really be needed 
    } 
    # ...and don't forget to print the original line back again 
    say $_; 
} 
# end of file, print summary of last exon 
print join("\t", "X", $last_exon, $min_start, $max_end, $last_strand), "\n"; 

, 나는 선을 사용하면 해당 열의 이전의 수는 다른 두 번째 열에 숫자가 발생할 때마다 X로 시작하는 요약 행을 인쇄 할 것으로 가정하고있어 초 안에 숫자가 아닌 값이있는 d 열은 요약을 트리거해서는 안됩니다. 또한 파일 끝 부분에 요약 행이 필요할 것으로 예상됩니다.

$exon에 숫자 만 들어 있으면 $exon !~ /\D/ 표현식이 true를 반환합니다. (특히, 그것은 그렇게 빈 문자열이 너무 일치합니다하는 -numeric 문자를 포함하지 않는 여부를 테스트합니다.)

이후, 내가 생각하지 않은 가장자리의 경우 무리가 있습니다 I 데이터에서 가능한지 여부와 데이터가 발생했을 때 치료 방법을 모릅니다. 예를 들어, 조심하기 위해 엑슨 번호가 동일하게 유지되는 동안 가닥이 바뀌는 경우 드문 경우에 요약을 인쇄 할 수도 있습니다. 마찬가지로 신중한 프로그래머는 입력 파일이 비어 있거나 두 번째 열에 숫자가 아닌 값이 들어있는 첫 번째 행을 고려할 수 있습니다.

최소한 use warnings을 사용하면 항상 숫자로 간주되는 값 중 하나라도 그렇게 나오지 않으면 알 수 있습니다.

+0

고맙습니다.이 코드는 훌륭하게 작동하지만 첫 줄을 인쇄하지 않습니다. 파일 "1 9239 712 8571 + "로 시작하고 두 번째 줄부터 시작합니다. 그러나 고맙습니다 힙을 나는 나머지를 처리 ​​할 것입니다! – Karyo

+0

아, 어리석은 나를. 결정된. –

+0

시도했지만, 이번에는 첫 번째 줄이 두 번 인쇄되었습니다. 그래서 일단 'say $ _;' 첫 번째 chomp 라인에서 완벽하게 작동했습니다! 고맙습니다. – Karyo