简体   繁体   中英

How can I choose particular lines from a file with Perl

I have a file which I want to take all the lines which starts with CDS and a line below. This lines are like:

CDS             297300..298235
                      /gene="ENSBTAG00000035659"

I found this in your site:

open(FH,'FILE');

while ($line = <FH>) {
if ($line =~ /Pattern/) {
    print "$line";
    print scalar <FH>;
}
}

and it works great when the CDS is only a line. Sometimes in my file is like

CDS             join(complement(416559..416614),complement(416381..416392),
               complement(415781..416087))
               /gene="ENSBTAG00000047603"

or with more lines in the CDS. How can I take only the CDS lines and the next line of the ID??? please i need your help! Thank you in advance.

Assuming the "next line" always contains /gene= , one can use the flip-flop operator .

while (<>) {
   print if m{^CDS} ... m{/gene=};
}

Otherwise, you need to parse the CDS line. It might be sufficient to count parens.

my $depth = 0;
my $print_next = 0;
while (<>) {
   if (/^CDS/) {
       print;
       $depth = tr/(// - tr/)//;
       $print_next = 1;
   }
   elsif ($depth) {
       print;
       $depth += tr/(// - tr/)//;
   }
   elsif ($print_next) {
       print;
       $print_next = 0;
   }
}

You need to break the input into outdented paragraphs. Outdented paragraphs start a non-space character in their first line and start with space characters for the rest.

Try:

#!/usr/bin/env perl

use strict;
use warnings;

# --------------------------------------

my $input_file = shift @ARGV;
my $para = undef; # holds partial paragraphs

open my $in_fh, '<', $input_file or die "could not open $input_file: $!\n";
while( my $line = <$in_fh> ){

  # paragraphs are outdented, that is, start with a non-space character
  if( $line =~ m{ \A \S }msx ){

    # don't do if very first line of file
    if( defined $para ){

      # If paragraph starts with CDS
      if( $para =~ m{ \A CDS \b }msx ){
        process_CDS( $para );
      }

      # delete the old paragraph
      $para = undef;
    }
  }

  # add the line to the paragraph,
  $para .= $line;
}
close $in_fh or die "could not close $input_file: $!\n";

# the last paragraph is not handle inside the loop, so do it now
if( defined $para ){

  # If paragraph starts with CDS
  if( $para =~ m{ \A CDS \b }msx ){
    process_CDS( $para );
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM