Nalababu has asked for the wisdom of the Perl Monks concerning the following question:

I need help in parsing this output:
ENSMUSG00000027831 ENSTBEG00000008938 ortholog_one2one Euthe +ria 56.2942008486563 ENSMUSG00000027831 ENSLAFG00000011038 ortholog_one2one Euther +ia 58.5845347313237 ENSMUSG00000027831 ENSDORG00000014560 ortholog_one2one Sciuro +gnathi 43.9759036144578
and getting the value greater than 50.000 and printing that entry separately. this is my program i wrote but im getting error uninitialized value in split:
use strict; use warnings; use Getopt::std; my $le = "lethal_results.txt"; open(LE , "<", $le) or die ("Unable to open file $le: $!"); my @le_data = <LE>; my $le_data; close (LE); for( my$i=1; $i<= @le_data; $i++) { my @line = split(/\s+/,$le_data[$i]); my $width = 11; if(@le_data[5] >= 50.000) { my $data = $le_data[$i]; chomp $data; printf("%s%${width}s%${width}s%\t\t%.6g\n", $le_data[1],$le_data[2],$l +e_data[4],$le_data[6]); }
What is wrong with the code? How can i rectify it. I am not sure with what datatype to use for each value?

Replies are listed 'Best First'.
Re: Parsing in perl
by ikegami (Patriarch) on Jun 09, 2009 at 15:43 UTC

    @le_data contains the lines of the file (which is a total waste of memory, incidentally). @line contains the fields. You never use contents of @line.

    Also, your indexes make no sense. The fields are indexed 0 to 4, but you're accessing index 6.

    use strict; use warnings; my $width = 11; my $le = "lethal_results.txt"; open(LE , "<", $le) or die("Unable to open file $le: $!\n"); while (<LE>) { chomp; my @line = split(/\s+/, $_); if ($line[4] >= 50) { printf("%s%${width}s%${width}s%\t\t%.6g\n", @line[0,1,2,4] ); } }
Re: Parsing in perl
by McDarren (Abbot) on Jun 09, 2009 at 16:05 UTC
    Hi :)

    You're doing a lot of convulted stuff there with arrays and C-style loops, that really isn't necessary.

    When you need to examine a file line by line, you're usually better reaching for a 'while' loop, rather than a 'for' loop.

    Here is a slightly more perlish way to do what you want.

    #!/usr/bin/perl use strict; use warnings; my $le = 'lethal_results.txt'; open my $in, '<', $le or die "Cannot open $le:$!\n"; while (<$in>) { chomp; my $foo = (split)[4]; print "$foo\n" if $foo >= 50; } close $in;
    Of course, you could always just do something like:
    perl -lane 'print $F[4] if $F[4] >= 50' < lethal_results.txt

    Cheers,
    Darren :)

Re: Parsing in perl
by almut (Canon) on Jun 09, 2009 at 15:42 UTC

    Try something like this:

    ... for (@le_data) { my @line = split /\s+/; if ($line[4] >= 50.000) { my $width = 11; printf "%s%${width}s%${width}s\t\t%.6g\n", @line[0,1,3,4]; } }
Re: Parsing in perl
by arc_of_descent (Hermit) on Jun 09, 2009 at 15:36 UTC

    Yor are declaring $le_data which you don't need. You already have the lines in the @le_data array. In Perl, you access an array element using $array_name. Just remove the

    my $le_data;

    line. And in the if condition, you need to do $le_data[5]


    --
    Rohan
Re: Parsing in perl
by ambrus (Abbot) on Jun 09, 2009 at 15:26 UTC

    You probably want $le_data[4] instead of $le_data[5].

    Update: sorry, let me try again. You probably want $line[4] instead of $le_data[5]; also change the outer for loop to go from 0 up to @le_data - 1 instead of from 1.

Re: Parsing in perl
by Bloodnok (Vicar) on Jun 09, 2009 at 15:20 UTC
    2 things:
    • I need help reading it - use <code> </code> tags round the output
    • Normally, we say please ;-)
    A user level that continues to overstate my experience :-))
Re: Parsing in perl
by wazoox (Prior) on Jun 09, 2009 at 15:29 UTC
    The "uninitialized value in split" error is probably due to empty lines in your input.
Re: Parsing in perl
by DStaal (Chaplain) on Jun 09, 2009 at 15:51 UTC

    Try this a moment:

    foreach my $val ( @le_data ) { my @line = split /\s+/, $val; my width = 11; ...

    Your actual problem is that arrays are zero-indexed, not one-indexed, but the above is a much more Perlish way to loop through all the values of the array.

Re: Parsing in perl
by Anonymous Monk on Jun 09, 2009 at 16:24 UTC
    Another way (golf anyone?)

    use strict; use warnings; open(LE , "<", $le) or die ("Unable to open file $le: $!"); my $width=11; while (<LE>) { my @line; printf("%s%${width}s%${width}s%\t\t%.6g\n", @line[0,1,2,4]) if (@line = split) && ($line[4] gt 50); } close LE;
Re: Parsing in perl
by bichonfrise74 (Vicar) on Jun 10, 2009 at 05:16 UTC
    Another way of doing it...
    #!/usr/bin/perl use strict; while (<DATA>) { print if ( (split)[4] > 50 ); } __DATA__ ENSMUSG00000027831 ENSTBEG00000008938 ortholog_one2one Euther +ia 56.2942008486563 ENSMUSG00000027831 ENSLAFG00000011038 ortholog_one2one Euther +ia 58.5845347313237 ENSMUSG00000027831 ENSDORG00000014560 ortholog_one2one Sciuro +gnathi 43.9759036144578
Re: Parsing in perl
by ikegami (Patriarch) on Jun 09, 2009 at 15:44 UTC

    @le_data contains the lines of the file (which is a total waste of memory, incidentally). @line contains the fields. You never use contents of @line.

    Also, your indexes make no sense. The fields are indexed 0 to 4, but you're accessing index 6.

    use strict; use warnings; my $width = 11; my $le = "lethal_results.txt"; open(LE , "<", $le) or die("Unable to open file $le: $!\n"); while (<LE>) { chomp; my @line = split(/\s+/, $_); if ($line[4] >= 50) { printf("%s%${width}s%${width}s%\t\t%.6g\n", @line[0,1,2,4] ); } }