Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

splitting lines a number of times

by perl-rob (Initiate)
on Apr 01, 2009 at 15:39 UTC ( [id://754742]=perlquestion: print w/replies, xml ) Need Help??

perl-rob has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm working with a line of numbers from a file in the form:
( 0, 670); 3.2; 7.8; 9.4; 10.2; 12.6;
I know that I can use these lines:
$line = <FILE>; @split1 = split(/;/, $line);
which will result in the array @split1 containing:
@split1[0] = ( 0, 670) @split1[1] = 3.2 @split1[2] = 7.8 etc.
the 1st and 2nd elements are already fine, but I need to get the numbers out of the 0th element. If I then combine the following:
$line = <FILE>; @split1 = split(/;/, $record); @split2 = split(/,/, @split1[0]); @split3 = split(/\(/, @split2[0]); @split4 = split(/\)/, @split2[1]); $test1 = @split3[1]; $test2 = @split4[0];
then $test1 and $test2 then contain the numbers I want. Two questions, is there a more elegant way to do this, I'm sure there must be. Second question, can I then use $test1 and $test2 just like numbers, i.e. perform operations on them like +, -, * and /? Thanks in advance for any help.

Replies are listed 'Best First'.
Re: splitting lines a number of times
by kennethk (Abbot) on Apr 01, 2009 at 15:51 UTC

    If you don't care about how many numbers are in your parentheses and know all lines follow the same format, you could remove the parentheses from the input line and then split on either a comma or a semicolon. In particular, judicious use of | (or) could save you typing. This is all covered in perlre and perlretut. You could do it like this:

    my $line = <FILE>; $line =~ s/\(|\)//g; my @numbers = split /\,|\;/, $line;

    It'd make sense to swap to a different delimiter to reduce the LTS, of course.

    Update: Of course there's no need to use split at all. The one liner:

    my($test1,$test2,@numbers) = (my $line = <FILE>) =~ /[0-9.]+/g;

Re: splitting lines a number of times
by ELISHEVA (Prior) on Apr 01, 2009 at 16:03 UTC

    There is definitely no need for all of those splits. If you want an array that contains all numbers, e.g. you want to replace a single array element "(0,670)" with two array elements one for each number. You could do the following:

    use strict; use warnings; while (my $line = <DATA>) { #remove all whitespace $line =~ s/\s//g; #split line my @aFields = split(/;/, $line); #remove parenthesised field my $sFld1 = shift @aFields; #convert parenthesized field to numbers my ($sNoParens) = ($sFld1 =~ /^\(([^)]*)\)$/); my @aSubFields = split(/,/, $sNoParens); # if you want to make sure there are only N # numbers, do your checks here. #put the numbers where fld0 was originally unshift @aFields, @aSubFields; #print the result print "<@aFields>\n"; } __DATA__ ( 0, 670); 3.2; 7.8; 9.4; 10.2; 12.6;

    See shift and unshift for more information.

    Best, beth

Re: splitting lines a number of times
by jethro (Monsignor) on Apr 01, 2009 at 16:03 UTC

    You could use a regexp to get the values:

    ($test1,$test2)= $split1[0]=~/\(\s*(\d+),\s*(\d+)/;

    It looks more complicated than it is because '(' has to be escaped when you want to search for it in a regular expression. The other parens in the search pattern are used as capture markers, anything between them is given back as a list in list context

    And yes, you can use the numbers to perform any operations, any string that looks like a number can be used as a number

    UPDATE: corrected the array access

Re: splitting lines a number of times
by Nkuvu (Priest) on Apr 01, 2009 at 16:06 UTC

    YAWTDI

    $line =~ s/[(),;]//g; my @split1 = split " ", $line;

    And yes, once you have these split up, they can be used in numeric calculations.

    Just a quick note, when you're referring to a single element of an array, use $split1[0] rather than @split1[0]. See "perldoc -q @" and look at the answer for "What is the difference between $array[1] and @array[1]?"

Re: splitting lines a number of times
by repellent (Priest) on Apr 01, 2009 at 17:02 UTC
    Just extract the numbers directly:
    use Regexp::Common; my @split = $line =~ /$RE{num}{real}/g;
Re: splitting lines a number of times
by jwkrahn (Abbot) on Apr 01, 2009 at 16:37 UTC

    You may want something like this:

    $ perl -le' my $line = "( 0, 670); 3.2; 7.8; 9.4; 10.2; 12.6;"; my @split1 = $line =~ /\d+(?:\.\d+)?/g; print for @split1; ' 0 670 3.2 7.8 9.4 10.2 12.6
Re: splitting lines a number of times
by linuxer (Curate) on Apr 01, 2009 at 17:46 UTC

    There is no need for regex. It only takes a tr///d and a simple split():

    while ( my $line = <DATA> ) { chomp $line; # backup of line, in case we need original version later my $line_copy = $line; # transliterate ',' into ';' remove '(', ')' and space(0x20) $line =~ tr/,() /;/d; # split at ';' my ( $first, $second, @rest ) = split /;/, $line; # do your work }
      Excellent, works exactly how I wanted it to and makes the code nice and self explanatory, also got me to read about transliteration, so thanks for that and for all the other answers!
Re: splitting lines a number of times
by Bloodnok (Vicar) on Apr 01, 2009 at 16:46 UTC
    Hmmm, must be getting bored & need a break ...

    TIMTOWTDI (where the it in question is the extraction of the numbers in order from the line) -

    perl -MData::Dumper -e 'print Dumper grep length $_, split /[^\d\.]+/ +, "( 0, 670); 3.2; 7.8; 9.4; 10.2; 12.6;"'
    returns
    $VAR1 = '0'; $VAR2 = '670'; $VAR3 = '3.2'; $VAR4 = '7.8'; $VAR5 = '9.4'; $VAR6 = '10.2'; $VAR7 = '12.6';
    as, I believe, required

    A user level that continues to overstate my experience :-))

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://754742]
Approved by ELISHEVA
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2024-04-25 17:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found