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

Greetings again good and saintly monks,

This is an interesting little regex problem that grew out of a recent class assignment:

Basically I want to take a line of text that contains values in Chinese national currency like this:

__DATA__ Hello all! Today I bought breakfast for 02.50 and lunch for 10.20 + Dinner was a real splurge at 21.00. __END__

And convert it and put it out in American dollars like this:

__DATA__ Hello all! Today I bought breakfast for 00.32 and lunch for 01.30 +. Dinner was a real splurge at 02.67. __END__

note that it is ok to keep the 0s on the left side of the numbers after the conversion.

I have managed to come up with something that looks like this:

my $string = <>; my $word; ### # I need help fixing this split function so that I can match the strin +gs below but # still keep the formatting from the original text. ### my @array = split(/*regex help needed here!*/, $string); while(@array){ $word = shift(@array); if($word = ~ /[0-9][0-9][.][0-9][0-9]/)){ ### #I have figured out the math to do the currency conversion ### print “$word”; } else{ print “$word”; } }

Basically I think it comes down to the fact I need help making the split function more intelligent. Is this possible, or am I asking too much from a simple regex?

Thanks for all help and opinions,

-mox

Replies are listed 'Best First'.
Re: Crafting a regex for a split() function...
by GrandFather (Saint) on Nov 23, 2006 at 01:24 UTC

    You can do it in one with:

    use strict; use warnings; use constant TO_US => 0.127; while (<DATA>) { s/(\d+.\d+)/convert($1)/eg; print; } sub convert { return sprintf "%.2f", $_[0] * TO_US; } __DATA__ Hello all! Today I bought breakfast for 02.50 and lunch for 10.20 Di +nner was a real splurge at 21.00.

    Prints:

    Hello all! Today I bought breakfast for 0.32 and lunch for 1.30 Dinn +er was a real splurge at 2.67.

    DWIM is Perl's answer to Gödel

      I didn't even know you could call a subroutine from inside a regex. Wow, this crazy language gets cooler and cooler...

      Just to be certain, the value for the match of /(\d+.\d+)/ is $1 and is then carried into sub convert as the value $_ ?

      Thank you very much!

      -mox

        I didn't even know you could call a subroutine from inside a regex.

        The replace expression of the substitution operator is treated as Perl code rather than a string literal when the e modifier is used.

        Ref: perlop

        Just to be certain, the value for the match of /(\d+.\d+)/ is $1 and is then carried into sub convert as the value $_ ?

        No. A subroutine's arguments are found in @_ (no relation to $_). $_[0] (again, no relation to $_) is the first element of @_, so it's the first argument of the subroutine.

        Ref: perlsub