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

MacBook 10.6.8, Perl 5.16.3

Dear munificent providers of wisdom and knowledge,

Consider a string "1 2 3*2 4 5x3". I'd like to turn this into "1 2 3 3 4 5 5 5" (but at a later date I might change my mind and turn "3*2" into "6" etc, but we'll leave that for the nonce).

What would be uber-cool is something like:

s/(\d+)[xX*](\d+)/\1 x \2/g

(possibly with a trailing "x" modifier to prettify it) where of course the last "x" is whatever is needed to get the repetition operator. The background is that I'm writing a simple stats analysis script, and I'd like to generate test data for it by hand.

As an aside, I've learned that geometric means and harmonic means aren't too happy about zero etc (yes, I know that solutions exist)...

Breathes there such a beast? I'm guessing that it will involve some imaginative use of eval() etc (which will also allow me to use expressions) but it won't quite click.

Ta muchly.

-- Dave

Replies are listed 'Best First'.
Re: Search and replace with expansion
by McA (Priest) on Aug 07, 2014 at 11:52 UTC
    s/(\d+)[xX*](\d+)\s*/eval("'$1 ' x $2")/ge;

    McA

      Nice! But note that you can get the effect of the eval by adding a second /e modifier instead:

      22:18 >perl -wE "my $s = '1 2 3*2 4 5x3'; $s =~ s/(\d+)[xX*](\d+)\s*/q +q['$1 ' x $2]/gee; say qq[\n|$s|];" |1 2 3 3 4 5 5 5 | 22:19 >

      Hope that’s of interest,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Thank you for that comment, Athanasius!

        It is interesting, at least for me.

        McA

Re: Search and replace with expansion
by Anonymous Monk on Aug 07, 2014 at 12:45 UTC

    s/(\d+)[xX*](\d+)/@{[($1) x $2]}/g;

      Much nicer, IMHO. Thanks.

Re: Search and replace with expansion
by AnomalousMonk (Archbishop) on Aug 07, 2014 at 13:30 UTC
    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = '1 2 3*2 4 5x3 6X4'; print qq{before: '$s'}; ;; my %operator = ( '*' => sub { return $_[0] * $_[1]; }, 'x' => sub { return join q{ }, ($_[0]) x $_[1]; }, ); ;; $s =~ s{ (\d+) ([xX*]) (\d+) } { $operator{lc $2}->($1, $3) }xmsge; print qq{after: '$s'}; " before: '1 2 3*2 4 5x3 6X4' after: '1 2 6 4 5 5 5 6 6 6 6'
Re: Search and replace with expansion
by davehorsfall (Novice) on Aug 08, 2014 at 06:54 UTC

    Many thanks, all; there's some neat ideas there. I guess I just needed a push in the right direction; I'd forgotten about the "e" modifier, for example.

    I'll work something out that not only allows me to expand the terms, but also evaluate them and insert constants such as square roots and "pi" etc.

    Thanks again.

    -- Dave