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

Perl's distinct difference with other langages is the use of pattern matches and my greatest diffulty. I conduct benchmarking of new systems and gather the numerical data for internal reporting. Writing numerical regular expressions for more than one set of numbers never seems to work for me. For examle,

iters = 320 (3.05s) aver = 9568.34 us (9603.45 us, 1.01s, 99.79%)

contains six numerical sets of numbers. I tried

if (ln =~ /(\[+-]d) +(\[+-]d.d) +(\[+-]d.d) +(\[+-]d.d) +(\[+-]d.d) +( +\[+-]d.d)/) { do something}

Of course this doesn't work. I have tried others with the same amoount of sucess. I would like to know how to handel numerical regularguar expressions of this type?

Thanks to all that respond.

Earl Jackson

20060403 Janitored by Corion: Added formatting, code tags

Replies are listed 'Best First'.
Re: Numerical Regular Expression for pattern match
by wfsp (Abbot) on Apr 03, 2006 at 11:38 UTC
    Something like this?

    #!/usr/bin/perl use warnings; use strict; my $data = q|iters = 320 (3.05s) aver = 9568.34 us (9603.45 us, 1.01s, + 99.79%)|; my @numerics; @numerics = ($data =~ /([\d\.]+)/g); print "*$_*\n" for @numerics;
    Output:
    ---------- Capture Output ---------- > "c:\perl\bin\perl.exe" _new.pl *320* *3.05* *9568.34* *9603.45* *1.01* *99.79* > Terminated with exit code 0.
Re: Numerical Regular Expression for pattern match
by McDarren (Abbot) on Apr 03, 2006 at 11:42 UTC
    If you define a number as anything containing an optional +/-, one or more digits, and an (optional) period, then you could simply do something like:
    m/([+\-]?[0-9\.]+)/g;
    Using your example, and putting this into a short script:
    #!/usr/bin/perl -w use strict; use Data::Dumper::Simple; my @numbers; while (<DATA>) { @numbers = $_ =~ m/([+\-]?[0-9\.]+)/g; } print Dumper(@numbers); __DATA__ iters = 320 (3.05s) aver = 9568.34 us (9603.45 us, 1.01s, 99.79%)
    Which gives:
    @numbers = ( '320', '3.05', '9568.34', '9603.45', '1.01', '99.79' );
    Does this help?

    Cheers,
    Darren :)

Re: Numerical Regular Expression for pattern match
by grinder (Bishop) on Apr 03, 2006 at 12:48 UTC
    I would like to know how to handel numerical regularguar expressions of this type?

    You might find that building up the pattern piece-by-piece will help you get a handle on constructing the final pattern.

    Given:

    iters = 320 (3.05s) aver = 9568.34 us (9603.45 us, 1.01s, 99.79%)

    The trickiest part matching a number with a decimal component, which is one or more digits, followed by a literal dot, and one or more digits. Which gives:

    my $num = qr/\d+\.\d+/;

    If you want to match positive or negative numbers, you would have to prefix that with an optional character class:

    my $num = qr/[-+]?\d+\.\d+/;

    But given the sample data, I'm not sure that that's even possible. But nonetheless, with this approach, which ever way you want to go doesn't really matter any more, because you just interpolate either of the above patterns into your overall pattern, which gives:

    /iters = \d+ \(($num)s\) aver = ($num) us \(($num) us, ($num)s, ($ +num)%\)/

    And you're done.

    • another intruder with the mooring in the heart of the Perl

Re: Numerical Regular Expression for pattern match
by ww (Archbishop) on Apr 03, 2006 at 13:21 UTC
    point 1:
    Your sample data has neither plusses nor minuses.. if that's characteristic, why are you attempting to match them?
    • if only some of them have signs, try [+-]? or, more explicitly, if less likely to give you a birdie or eagle, [+-]{0,1}

    but... point 2:
    As written, the "\" in your regex before each open_square_bracket escapes the bracket, meaning you're NOT matching against a character class, but rather against a string consisting of open_sq, +, -, close_sq. before the digits.

    and, point 3:
    Perl's implementation of RE is (ok, "is arguably") the best around, but perl is not the only language with regexen; javascript and java leap immediately to mind, and various *nix utilities implement them in more limited fashion (and with some variance of syntax)

    Online tutorials are numerous, perlretut and friends work well as quick refreshers, and the gold standard is Friedl's book, "Mastering Regular Expressions." (The link goes to O'Reilly's twofer (as of April 06) offer; the Stibblebine "Pocket Reference"

Re: Numerical Regular Expression for pattern match
by puudeli (Pilgrim) on Apr 03, 2006 at 12:56 UTC
    Have you considered utilizing Regexp::Common? This gargantuan module is almost omnipotent :-)
    --
    seek $her, $from, $everywhere if exists $true{love};
Re: Numerical Regular Expression for pattern match
by QM (Parson) on Apr 04, 2006 at 04:00 UTC
    You wrote:
    if (ln =~ /(\[+-]d) +(\[+-]d.d) +(\[+-]d.d) +(\[+- +]d.d) +(\[+-]d.d) +(\[+-]d.d)/) { do something}
    Here's where you went astray:

    \d matches a digit. \[+-]d.d matches an open_square_bracket, a plus, a minus, a close_square_bracket, a lowercase "d", any single character except newline, and another lowercase "d".

    If you want to match "3.4" or a similar x.x format number, you'd want \d\.\d.

    If you want to match a number, you can use one of the regexes in How do I determine whether a scalar is a number/whole/integer/float? (You'll want to remove the anchors and manage the capturing parens, see below.) Or you could use Regexp::Common.

    It's a good idea to go read the Regular Expression Reference and the Regular Expression Tutorial.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of