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

Hi,
I have a file that has lines like below:
1 *32:56 *35:5 40.6 2 *4:40 *9:110 30.2 3 *1:10 4 4 *8:90 *7:30 44 5 *17:9 5.0

I want to use a regular expression while processing this file and store lines such as
 1 *32:56 *35:5 40.6
into one variable and store lines such as
 3 *1:10 4
into another variable.
How can I do this?
I am trying to use if
 (/(\d+)(\*.*?:.*?)\s(\d+\.\d+)/)
to capture only those lines that look like
3 *1:10 4
but it does not seem to work as I expected? Any help please.
Buthuleji

Replies are listed 'Best First'.
Re: New to Perl
by BrowserUk (Patriarch) on Jun 23, 2010 at 19:39 UTC

    If the lines are distinguishable by them containing 2 '*'s, or not, then this would do the job:

    if( m[\*[^*]+\*] ) { print "file 1: $_"; } else { print "file 2: $_"; }

    The trick with regexes is only specify as much as you actually need.

    (Actually, only doing as much as is needed is a programming tenet that gets far too little respected.)

Re: New to Perl
by choroba (Cardinal) on Jun 23, 2010 at 19:49 UTC
    Your regex can work, but you have to make several adjustments:
    /^(\d+)\s+(\*[^:]*?:\S*?)\s(\d+\.?\d*)$/
    Basically: be careful whith *?. It sometimes matches more than you expect.
Re: New to Perl
by jrtayloriv (Pilgrim) on Jun 23, 2010 at 21:05 UTC
    Also, if you are trying to grab lines based on the number of fields, you could do:

    do_something_with($line) if (@{[split / /, $line]} == 3);

    ... to grab all of the lines that have 3 fields in them.

    The following is a little faster, but throws a warning:

    do_something_with($line) if ((scalar split / /, $line) == 3);

    Of course, if you are looking at more than the number of fields, these won't be useful ...
    --jrtayloriv
Re: New to Perl
by nvivek (Vicar) on Jun 24, 2010 at 09:18 UTC

    If you want to split the lines in an input file by using number of '*'.Then,you can use the regular expression to match the lines and push lines into two separate array.You check the following code.In this,I used both substitute as well as split function to do it.

    use strict; use warnings; use Data::Dumper; open FH,"<input" or die "can't open:$!"; #opening the input file my(@arr1,@arr2); #declaring the arrays to store those lines while(<FH>) { #reading line from a file one by one if(/\*[^*]+\*/) { #checking whether the line has two *'s in it push @arr1,$_ ; #pushing that line to an array1 } else { push @arr2,$_; #pushing that line to an array2 if it isn't having two +*'s in it } } close FH; #closing the file handle print "Lines with two *'s in it\n"; print @arr1; print "Lines with two *'s in it\n"; print @arr2;

    Another Way

    open FH,"<input" or die "can't open:$!"; #opening the input file while(<FH>) { #reading line from a file one by one if((split '\*',$_)==3) #splitting the line by using '*' and checking w +hether the split returns three which means three filds in it { push @arr1,$_ ; #pushing that line to an array1 } else { push @arr2,$_; #pushing that line to an array2 if it isn't having thre +e fields in it } } print "Lines with two *'s in it\n"; print @arr1; print "Lines with two *'s in it\n"; print @arr2; close FH; #closing the file handle