How to replace multiple patterns in one pass in Perl?
Question
How to replace multiple patterns in one pass in Perl?
Replacing multiple patterns in one pass in Perl can be accomplished efficiently using a single regex substitution with alternation, or by using a hash lookup combined with the s/// operator and the e (evaluate) flag. This approach helps avoid multiple traversals of the string, which would happen if you performed several separate substitutions one after the other.
Basic Approach Using Alternation
You can match multiple patterns by combining them using the pipe | operator inside parentheses. Then, inside the replacement part, you decide what to substitute depending on the match. Using the e modifier allows you to run Perl code in the replacement part.
Example: Replace several words with corresponding ones in one pass
use strict;
use warnings;
my $text = "I like cats, dogs, and birds.";
# Define replacements in a hash
my %replacements = (
cats => 'felines',
dogs => 'canines',
birds => 'avians',
);
# Single substitution with alternation and code evaluation
$text =~ s/\b(cats|dogs|birds)\b/$replacements{$1}/g;
print "$text\n";
Output:
I like felines, canines, and avians.
Explanation and Perl-Specific Concepts
s///is Perl's substitution operator. It searches with a regex on the left and replaces with something on the right.- The
|inside the regex means alternation, i.e., matchcatsordogsorbirds. \bis a word boundary anchor so thatcatswon't matchscattered.$1holds the matched text inside the parentheses (capture group 1).- Using
/$replacements{$1}/greplaces all matches (gmodifier). - If you wanted more complex logic, you can use the
emodifier to evaluate Perl expressions in the replacement.
Alternative: Using e Modifier For More Complex Replacements
If replacements require some computation, you can use the e modifier:
$text =~ s/\b(cats|dogs|birds)\b/ do {
my $key = $1;
ucfirst($replacements{$key});
}/ge;
This uppercases the first letter of each replacement word.
Common Pitfalls
- Not using word boundaries (
\b) can cause partial matches inside other words. - Order matters if patterns overlap (e.g.,
catandcats). Regex alternation consumes the first matching pattern. - For very large sets of replacements, building a regex with all words may affect performance—consider other approaches like
Text::Rewritein CPAN (but note your no-external-libs constraint). - Ensure the hash keys exactly match the variants in your text unless you extend the pattern to cover them.
Summary
Perl’s flexible regex engine and substitution operators let you cleanly replace multiple different patterns in a single pass by combining patterns in an alternation group and using a hash for lookups. This style is idiomatic and efficient in Perl's text-processing tasks.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 7ms
I like felines, canines, and avians.
(empty)