This is a test version of Biostars. For the public version, visit https://www.biostars.org.
Help Me Finish This Perl Code To Extract A Column In A Table

Hi, I have a question similar to this one:

http://www.biostars.org/post/show/50142/any-modules-available-to-parse-this-file/#50156

I adapted my code from JCs answer in that post. Thanks JC.

Here is an example of the data file data I am opening and trying to read the columns of. The values are delimited by 4 spaces.

A bunch of junk up here. Paragraph before getting to table.

NO.  RES   DSC_SEC PROB_H    PROB_E    PROB_C
1     k      C     0.047     0.240     0.713     
2     l      C     0.067     0.365     0.568     
3     n      C     0.067     0.365     0.568     
4     f      E     0.045     0.613     0.342     
...

Here is the code I have tried, which doesn't print anything. I want to be able to gather the data from PROB_H, PROB_E, PROB_C and have them in separate lists so that I can do stuff like take the averages of them.

use strict;
use warnings;

open(FILE, "file_data.txt") or die "Cannot open file: $!";

my @data = <FILE>;

while (<FILE>) {
    next if m/^No./;
    chomp;
    my ($NO, $RES, $DSC_SEC, $PROB_H, $PROB_E, $PROB_C) = split(/\s+/, @data);
    print "$PROB_H";
}

close(FILE);
perl data extraction

Some people are harsh :) Someone probably thought this was a rather basic Perl programming question, as opposed to a bioinformatics research question.

Two obvious errors straight off: (1) you have not escaped the period in your regular expression (so it will match "all characters"); (2) your data contains lines starting with NO (all upper-case) but your regular expression is looking for lines starting with No (lower-case "o").

Basically, you want to implement the 'cut' unix command in Perl? Specifically, something like tail -n +2 | cut -c18-26?

3 answers

It would probably be better to ask this question at stackoverflow.

Without a file it is kinda difficult to debug, but this may do the trick. You could also just use grep | awk ....

#/usr/bin/perl
use strict;
use warnings;

open(my $FH, <, "file_data.txt") or die "Cannot open file: $!";
LINE: while (my $line = <$FH>) {
    chomp $line;
    next LINE unless $line =~ /^[0-9]/;
    my ($NO, $RES, $DSC_SEC, $PROB_H, $PROB_E, $PROB_C) = split /\s+/,  $line;
    print "$PROB_H\n";
}
close($FH);

That gives me my column, thanks. I'm new to perl, what is the function of LINE: and $_ in this?

^ start with, a numeric value [0-9].

You can name your loops in perl. It can be useful to keep track of things. $_ is a special variable. In your script above it contained the line.

It also ends up printing one of the words up in the paragraph. Can we make it start on the header of the table, and grab the numbers below the header, like I tried before?

Or as suggested keep it simple

[your prompt]$ grep '^[0-9]' yourfile.txt | awk '{print $4}'

to print out the fourth column of lines in yourfile.txt that start with a number

There are a couple of problems with your script. It isn't necessary to read the file into an array as you are going to iterate over the file line by line. Also your test for throwing out non matching lines is only going to match a line starting with "No." and not the other non-matching lines in the file.

     use strict;
     use warnings;

     open(FILE, "file_data.txt") or die "Cannot open file: $!";

     while (my $line = <FILE>) {
#unless the line begins with a number followed by 
#one or more whitespace characters, skip it.
         unless ($line =~ m/^\d+\s+/) {next;}   
         chomp $line;
         my ($NO, $RES, $DSC_SEC, $PROB_H, $PROB_E, $PROB_C) = split(/\s+/, $line);
         print "$PROB_H\n";
        }

    close(FILE);

There is a line in the paragraph that begins with a number. Can I exclude it for containing certain words.

Such as make that unless clause: unless ($line =~ m/^\d+\s+|residues/) {next;}
because that line that starts with a number has the word residues in it. This does not work for some reason.

Log in to answer this question.