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

Hi,
I'm a lamer-newbie, so please excuse me if this is a dumb question.. I have been mulling over it now for a couple hours, and I can't think of a good way to do what I want. I am not even sure how to search for what I'm trying to do either, so here goes:
Best to give an example:

...load an array of words then foreach it
<snip>
if(/nce|nse/) { s/$&/replace with what it's not/i; print; }
So.. if I have two strings I'm searching for, I want it to replace with the the other string; IOW, if I find "nse", I want to replace with "nce" and visa versa.. Every thing I think of seems more complicated than:

if(nse) { s/nse/nce/i; print; } if(nce) { s/nce/nse/i; print; }
If that's the only way to do it, sobeit.. but I'm thinking there has to be a more elegant way to tell it to replace with b if it finds a, or a if it finds b.

Edit by thelenm: added code tags

Replies are listed 'Best First'.
Re: Search and replace logic
by Roger (Parson) on Nov 19, 2003 at 03:44 UTC
    How about using a single regular expression?
    my $str = "florence, defense"; $str =~ s/n(c|s)e/$1 eq 'c'?'nse':'nce'/ge; print "$str\n";
    And the output is -
    florense, defence
    which is just as expected.

      This did what I was looking for.

      THANKS!!!
Re: Search and replace logic
by !1 (Hermit) on Nov 19, 2003 at 03:44 UTC
    s/(n(?i:s|c)e)/$1 ^ "nse" ^ "nce"/gie;

    Of course, that's only if you want to keep its case (mad props to Abigail-II for the nifty trick :-). However, if you want a more general mechanism for mapping particular words to other words and don't mind about the case:

    my %word_map = ( nce => "nse", nse => "nce" ); my $re = join "|", map qr/\Q$_/i, keys %word_map; s/($re)/$word_map{lc $1}/ge; print

    That would be a more general mechanism even though it doesn't keep case.

    Hope this helps.

Re: Search and replace logic
by ysth (Canon) on Nov 19, 2003 at 03:46 UTC
    s/(nce|nse)/${{nce=>nse=>nse=>nce=>}}{$1}/g
    Or the perhaps simpler to understand:
    %repl = (nce => 'nse', nse => 'nce'); foreach (...) { s/(nce|nse)/$repl{$1}/g; }
    I see you have //i. If you want to preserve equivalent case in the replacements, you'll have to specify all the different combinations of case in the hash, or use s/(whatever)/mangle("$1")/ie where mangle is a sub that does whatever transformation you want.
      Nice. The parent message is beautiful code. ++

      Sometimes I think I'm a perl freak for not prefering the obfu versions .... ;-)

      -------------------------------------
      Nothing is too wonderful to be true
      -- Michael Faraday

Re: Search and replace logic
by cleverett (Friar) on Nov 19, 2003 at 03:45 UTC
    Try something like this (you may have to diddle the modifiers to s/// a touch):
    my @data = <DATA>; my @swap = qw/nce nse/; my %replace = ( @swap, reverse @swap ); my $search_for = join('|', keys %replace); s/($search_for)/$replace{lc $1}/gi foreach @data; __DATA__ incense license luminance
    update: added a /g to the s///