You can do this the quick and dirty way, or the quick and clean way:
In both cases you need a hash word => replacement
With the quick and dirty way, you then build the left part of the substitution by joining the keys of the hash with a '|'. In order to deal with overlapping words (eg 'cat' and 'catogan') you need to place the longest option first, by doing a sort reverse
on the keys of the hash. You still can't deal with meta-characters in the words to replace (eg 'cat++').
The quick and clean way uses Regexp::Assemble to build the left part of the regexp. It deals natively with overlapping words, and it is simple to get it to deal with meta-characters in the words to replace.
Once you have the word to replace, you then replace it with the corresponding entry in the hash.
Below is a bit of code that shows the 2 methods, dealing with various cases:
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 6;
use Regexp::Assemble;
my $mystring = "My cat likes to eat tomatoes.";
my $expected = "My dog likes to eat pasta.";
my $repl;
# simple case
$repl= { 'cat' => 'dog', 'tomatoes' => 'pasta', };
is(
repl_simple($mystring, $repl),
$expected,
'look Ma, no module (simple)'
);
my $re= regexp_assemble($repl);
is(
repl_assemble($mystring, $re),
$expected,
'with Regex::Assemble (simple)'
);
# words overlap
$mystring = "My cat (catogan) likes to eat tomatoes.";
$expected = "My dog (doggie) likes to eat pasta.";
$repl= {'cat' => 'dog', 'tomatoes' => 'pasta', 'catogan' => 'doggie', };
is(
repl_simple($mystring, $repl),
$expected,
'no module, words overlap'
);
$re= regexp_assemble( $repl);
is(
repl_assemble($mystring, $re),
$expected,
'with Regex::Assemble, words overlap'
);
# words to replace include meta-characters
$mystring = "My cat (felines++) likes to eat tomatoes.";
$expected = "My dog (wolves--) likes to eat pasta.";
$repl= {'cat' => 'dog', 'tomatoes' => 'pasta', 'felines++' => 'wolves--', };
is(
repl_simple($mystring, $repl),
$expected,
'no module, meta-characters in expression'
);
$re= regexp_assemble( $repl);
is(
repl_assemble($mystring, $re),
$expected,
'with Regex::Assemble, meta-characters in expression'
);
sub repl_simple {
my( $string, $repl)= @_;
my $alternative= join( '|', reverse sort keys %$repl);
$string=~ s{($alternative)}{$repl->{$1}}ig;
return $string;
}
sub regexp_assemble {
my( $repl)= @_;
my $ra = Regexp::Assemble->new;
foreach my $alt (keys %$repl)
{ $ra->add( '\Q' . $alt . '\E'); }
return $ra->re;
}
sub repl_assemble {
my( $string, $re)= @_;
$string=~ s{($re)}{$repl->{$1}}ig;
return $string;
}