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

I just discover s///e so I can s/x/"o" x 5/e which give "wxy" -> "woooooy". But what are other use of s///e ? thanks monks.

Replies are listed 'Best First'.
Re: how do I use s///e
by Abigail-II (Bishop) on Jan 26, 2004 at 10:42 UTC
    s/x/"o" x 5/e is rather inefficient, specially if you do it in a loop. It's inefficient because you ask Perl to execute something that always gives the same result. s/x/ooooo/ or $o = "o" x 4; ...; s/x/$o/ are more efficient.

    s///e is interesting if the result of the code in the replacement part depends on the match. s/(\d+)\s*\+\s*(\d+)/$1 + $2/e; for instance.

    Abigail

Re: how do I use s///e
by borisz (Canon) on Jan 26, 2004 at 10:42 UTC
    call a subroutine from there. This is very usefull whenever the replacement is not the same on each iteration.
    Boris
      Agreed. Combining the ability to call a subroute to do your bidding and back references makes for some very handy abilities.
      For example:
      Say I have a string:

      "The %NOUN% can jump very %ADVERB%"

      And say I have hash:
      %wordBank = ( NOUN => "kangaroo", ADVERB => "far", )

      I wanted to replace what is in the string with what is in the hash, so originally, I iterated through the hash and did a replace on the string as I found each hash key. This is terribly inefficient, so I reworked it to find items delimited by %..% in the string, and used the delimited keyword to directly call the value from the hash. This save me a lot of time, especially when %wordBank is very large.
      #!/usr/bin/perl -w use strict; sub safeReplace { my($hashkey,%hash) = @_; my $hash = \%hash; my $retval = ''; if (defined($hash{$hashkey})) { $retval = $hash{$hashkey}; } else { $retval = "\%$hashkey\%"; } return $retval; } sub preProcessStr { my($string,%options) = @_; $string =~ s/%(.+?)%/safeReplace($1,%options)/ge; return $string; } my %options = ( ARG1 => "test", ARG2 => "123...", ); my $string = 'Hello %ARG1%, counting down %ARG2% .. %NOT%'; $string = preProcessStr($string,%options); print "$string\n"

        I realize your code was mainly for demonstration purposes, but it can be shortened considerably. I'm sure this can be golfed down even more, but I came up with the following snippet, which I feel is simple yet not too obfuscated (and also demonstrates the use of s///e, so I guess it's not really too OT):

        #!/usr/bin/perl use strict; use warnings; my $str = 'The %NOUN% can jump very %ADVERB% with his %APPENDAGES%'; my %wb = ( NOUN => "kangaroo", ADVERB => "far", ); $str =~ s/%([^%]+)%/$wb{$1} || "\%$1\%"/ge; print "$str\n";

        Update: %s/\$template/\$str/g; silly mistake caused by last-minute-edits-without-testing. Thanks to Not_a_Number for the catch.

Re: how do I use s///e
by dominix (Deacon) on Jan 26, 2004 at 10:45 UTC
    there is a node from BooK that is 59 /e in which there is some demonstration. ;-)
    but basically look for search and replace in perlretut to have a better understanding.
    --
    dominix
Re: how do I use s///e
by Kageneko (Scribe) on Jan 26, 2004 at 17:43 UTC
    s///e is great when you're playing around with Filter::Simple:
    package Filter::ISA; use strict; use warnings; use Filter::Simple; FILTER_ONLY code => sub { s/package\s+(\w+?)\s+isa\s+(.+?);/"package $1; use base qw( " . join +(" ", split(",", $2)) . " );"/eg; }; 1;
    Usage:
    use Filter::ISA; package derived isa base1, base2;
Re: how do I use s///e
by halley (Prior) on Jan 26, 2004 at 17:42 UTC
    If you want to compute the replacements based on the item replaced, s///e is very convenient.
    s/(?<!0x)([1-9]\d*)/sprintf "0x%X", $1/eg

    I haven't tested this thoroughly, but this should convert any decimal constant in your source into a C/Perl-style hexadecimal constant. It doesn't handle underscores or floating-point well, but it should skip any already-hexadecimal or already-octal numbers.

    --
    [ e d @ h a l l e y . c c ]

Re: how do I use s///e
by Roy Johnson (Monsignor) on Jan 26, 2004 at 19:47 UTC
    You can test which of a set of alternatives match, as I did in this example.

    The PerlMonk tr/// Advocate
Re: how do I use s///e
by inman (Curate) on Jan 26, 2004 at 17:36 UTC
    In a templating system a substitution of this form can be used to do a lookup on variables being substituted with replacement from a pre-populated hash.
    my %myHash = (hello=>"Howdy", goodbye=>"See ya"); while (<DATA>) { s/\$(\w+)/$myHash{$1}/eg; print; } __DATA__ When I want to say hello I say $hello. When I want to say goodbye I say $goodbye!

    Update Whoops! Thanks Abigail! This started as an example that used a sub to do the look up in a database but I got all lazy and just did it as a hash. Some revised (incomplete) code below.

    s/\$(\w+)/dbLookup($1)/eg; sub dbLookup { # Do database lookup (which would take a few more lines!) return $lookedup ? $lookedup : ''; }
      There's no point in using /e in your code. Removing the /e yields the same results.

      Abigail

        To expand on this, whenever you have a (update: just) variable in the substitution, it's as if you said /e. In a sense, then, /e just becomes syntactic sugar that you can do away with:
        $ echo with bright knives he releaseth my soul | perl -wpe's/(\w+)/${\ +ucfirst($1)}/g' With Bright Knives He Releaseth My Soul