Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Is Group Substitution Possible?

by ketema (Scribe)
on Jul 28, 2005 at 19:49 UTC ( [id://479110]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks...I am always looking for one liners and I would like to know if it is possible to substitute a group of known substrings with a set of corresponding known values. For example:
$string = "Test: FileNames can't have / \\ and other special character +s";
Now I could easily substitute out...
$string =~ /\:/COLON/g; $string =~ /\//FSLASH/g; $string =~ /\\/BSLASH/g;
And the value of $string is:
"TestCOLON FileNames can't have FSLASH BSLASH and other special characters"
But I would like to know if its possible to do all the substitutions in one line with some sort of grouping.
Thanks

Replies are listed 'Best First'.
Re: Is Group Substitution Possible?
by Anonymous Monk on Jul 28, 2005 at 20:09 UTC
    #!/usr/bin/perl -w $string = "Test: FileNames can't have / \\ and other special character +s"; %s = (":" => "COLON", "/" => "FSLASH", "\\" => "BSLASH"); $t = (join "|", map quotemeta($_), (keys %s)); $string =~ s/($t)/$s{$1}/g; print "$string\n";
      This is perfect. It is much more elegant than what I had. Thank you.
      That's a nice trick! I was looping through each subsitution which is inefficient!

      cheers

      SK

      Update: ihb++ Thanks for the nice demonstration!

      After reading ihb's post it makes sense and looping is not inefficient after all. I spoke too soon! I guess I shouldn't have "assumed" something is inefficient without benchmarking it.

        I was looping through each subsitution which is inefficient!

        Not necessarily. Alternation can disable some optimizations that the regex engine uses. This becomes more noticable on larger strings.

        use strict; use warnings; use Benchmark qw(cmpthese timethese); my $orig = "Test: FileNames can't have / \\ and other special characte +rs"; $orig .= 'a' x 1000; my %substs = qw( : COLON / FSLASH \\\\ BSLASH ); sub loop { my $string = $orig; $string =~ s/$_/$substs{$_}/g for keys %substs; return; } my @substs = ( qr/:/ => 'COLON', qr/\// => 'FSLASH', qr/\\/ => 'BSLASH', ); sub loop2 { my $string = $orig; $string =~ s/$substs[$_]/$substs[$_ + 1]/g for map $_ * 2, 0 .. $#substs / 2; return; } my %s = qw( : COLON / FSLASH \\ BSLASH ); my $t = join "|", map quotemeta, keys %s; sub alter { my $string = $orig; $string =~ s/($t)/$s{$1}/g; return; } my %tests = ( loop => \&loop, loop2 => \&loop2, alter => \&alter, ); cmpthese(timethese(-2, \%tests)); __END__ Benchmark: running alter, loop, loop2 for at least 2 CPU seconds... alter: 3 wallclock secs ( 2.42 usr + 0.00 sys = 2.42 CPU) @ 16 +55.39/s (n=4011) loop: 2 wallclock secs ( 2.13 usr + 0.00 sys = 2.13 CPU) @ 64 +89.92/s (n=13843) loop2: 2 wallclock secs ( 2.02 usr + 0.00 sys = 2.02 CPU) @ 11 +480.97/s (n=23226) Rate alter loop loop2 alter 1698/s -- -72% -86% loop 6125/s 261% -- -48% loop2 11811/s 596% 93% --
        Note that the code isn't completely equivalent though. Using &loop or &loop2 you can replace a replacement. For instance, if a replacement has a colon in it &alter will leave it there while &loop will change it to "COLON".

        ihb

        See perltoc if you don't know which perldoc to read!

Re: Is Group Substitution Possible?
by sk (Curate) on Jul 28, 2005 at 20:06 UTC
    In your example you don't have a clear order in which the pattern can happen so the second part of the code will be useful. If the order is set then you can use the first part of the code

    #!/usr/bin/perl -w $string = "Test: FileNames can't have / \\ and other special character +s"; $string =~ s/(.*):(.*)\/(.*)\\(.*)/$1COLON$2FSLASH$3BSLASH$4/; # Note +greedy substituion in place print $string,$/; my %subs = qw(: COLON / FSLASH \\\\ BSLASH); $string =~ s/$_/$subs{$_}/ for (keys %subs); print $string,$/;
    Output

    TestCOLON FileNames can't have FSLASH BSLASH and other special charact +ers TestCOLON FileNames can't have FSLASH BSLASH and other special charact +ers
      The order could possibly vary.
Re: Is Group Substitution Possible?
by tlm (Prior) on Jul 29, 2005 at 02:18 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://479110]
Approved by Paladin
Front-paged by friedo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (6)
As of 2024-04-23 09:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found