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

hi guys !

Is there a way in one regexp to replace more than one word in a string as follows:
my $str = 'I have a green shirt and a blue hat'; my ($YELLOW, $RED) = qw(yellow red); # I wish that could have worked somehow $str = tr/green,blue/$yellow,$RED/; # requested result print $str; # would print: I have a yellow shirt and a red hat
Anyone?

Hotshot

Replies are listed 'Best First'.
Re: tr///
by japhy (Canon) on Jan 24, 2002 at 21:42 UTC
    tr/// is strictly for character-to-character transliteration. You want substitution.
    %change = qw( green yellow blue red ); my $rx = join '|', # alternation map { quotemeta } # make it a safe string sort { length($b) <=> length($a) } # so that 'broken' matches before 'broke' keys %change; $str =~ s/($rx)/$change{$1}/g;
    This is a common idiom.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: tr///
by archen (Pilgrim) on Jan 24, 2002 at 22:53 UTC
    $str = tr/green,blue/$yellow,$RED/;

    The above post states the answer to your question, but I'd point out another thing. In the above code you're using the wrong operator. in order to bind tr///, s///, or m/// to a string you need to use the =~ operator like so:

    $str =~ tr/g/o/;

    It's a common mistake so maybe it's just a typo when you submitted the code. The way you have it written, tr/// is in scalar context and will just return how many times it replaced something.

    Edited: fixed typo -- japhy

    Update:See? I told you it was a common mistake! ;) . Maybe I need another cup of coffee... or need to stop using the default variable so much..