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

Hi, I'm trying to read numbers from a file with the following format: 25 ((18 25 4) (3 12 1)) I use the following code:

open (INFILE,$post) or die "**| Couldn't open file general: $post"; while (<INFILE>) { @words = split; } close (INFILE); $L=($words[2]+$words[5]); $D=($words[1]+$words[4]); $M=($words[3]+$words[6]);

$L and $M get the right value (L=37, M=5) but $D=0 instead of the expected value of 21. I guess this is due the presence of parentheses. How can I read the correct values? How to specify that parentheses should not be read? Thank you very much, Lluis

Replies are listed 'Best First'.
Re: Trying to read numbers from a text file
by toolic (Bishop) on Feb 28, 2016 at 19:04 UTC
    One way is to remove the parentheses before splitting. Here I replace all parens with a single space just in case your input ever has adjacent closing/opening parens, like (1 2 3)(4 5 6):
    use warnings; #use strict; while (<DATA>) { chomp; tr/()/ /; @words = split; } $L=($words[2]+$words[5]); $D=($words[1]+$words[4]); $M=($words[3]+$words[6]); print "L=$L D=$D M=$M\n"; # Output: L=37 D=21 M=5 __DATA__ 25 ((18 25 4) (3 12 1))
Re: Trying to read numbers from a text file
by hippo (Archbishop) on Feb 28, 2016 at 19:09 UTC

    If you are only using integers, match on digits.

    #!/usr/bin/env perl use strict; use warnings; my $line = "25 ((18 25 4) (3 12 1))\n"; my @words = $line =~ /(\d+)/g; my $M = $words[1] + $words[4]; print "$M\n";
Re: Trying to read numbers from a text file
by AnomalousMonk (Archbishop) on Feb 28, 2016 at 19:21 UTC

    Also be aware that because of the way your file-reading while-loop is set up, you are getting values for  $L $D $M etc. only for the very last line of the file. (Update: It might also be wise to introduce the use of warnings and strict into your code!)


    Give a man a fish:  <%-{-{-{-<

Re: Trying to read numbers from a text file
by Laurent_R (Canon) on Feb 28, 2016 at 21:14 UTC
    Using the use strict; and use warnings pragmas (something that you should always insert at the beginning of your programs) would have given you the following warnings:
    Argument "(3" isn't numeric in addition (+) at ... line 8. Argument "((18" isn't numeric in addition (+) at ... line 8.
    But before that, some others things would have had to be fixed in your program, especially you would have had to declare your variables with the my keyword.

    Help the compiler to help you, always use strict; and use warnings;

Re: Trying to read numbers from a text file
by GrandFather (Saint) on Feb 29, 2016 at 00:37 UTC

    What is the significance of the parenthesis? Can you afford to simply ignore them? What is your bigger picture goal with this code?

    Others have offered various ways to extract the numbers. That may seem like the "first step" in achieving the bigger picture goal, but it may instead lead to a lot of frustration because you have lost important information (the relationship between the numbers) in the very first step.

    Premature optimization is the root of all job security
Re: Trying to read numbers from a text file
by johngg (Canon) on Feb 28, 2016 at 23:48 UTC

    You could split using a character class containng space characters and left and right parentheses, see perlre.

    $ perl -Mstrict -Mwarnings -E ' my $line = q{25 ((18 25 4) (3 12 1))}; my @nums = split m{[\s()]+}, $line; say qq{@nums};' 25 18 25 4 3 12 1 $

    I hope this is helpful.

    Cheers,

    JohnGG

Re: Trying to read numbers from a text file
by jdporter (Paladin) on Feb 29, 2016 at 03:24 UTC
    use List::MoreUtils 'pairwise'; while (<DATA>) { y/ ()/,[]/; my( $D, $L, $M ) = eval { ( $a, $b ) = @{ [ eval ]->[ 1 ] }; pairw +ise { $a + $b } @$a, @$b }; print $@ || "$D $L $M\n"; }

    Forgive me, for I have sinned.

    I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.
Re: Trying to read numbers from a text file
by jcb (Parson) on Feb 29, 2016 at 05:06 UTC

    It might be easier to write out a regular expression for this:

    while (<INFILE>) { chomp; m/(\d+)\s+\(\((\d+)\s+(\d+)\s+(\d+)\)\s*\((\d+)\s+(\d+)\s+(\d+)\)\ +)/; $L = $3 + $6; $D = $2 + $5; $M = $4 + $7; }

    Well, it seemed like a good idea... (and it does pass the given test case)

Re: Trying to read numbers from a text file
by biscarri (Initiate) on Mar 01, 2016 at 17:17 UTC

    Thank you very much to every one for the advise: toolic, hippo, AnomalousMonk, Laurent_R, GrandFather, johngg, jdporter & jcb I have a big file, which is a results listing of an iterative process, and I need to read only the last line. Finaly I have managed to remove all parentheses from the file, using the command:

    s/([()])//g

    Best regards, Lluis