text-processing intermediate

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., match cats or dogs or birds.
  • \b is a word boundary anchor so that cats won't match scattered.
  • $1 holds the matched text inside the parentheses (capture group 1).
  • Using /$replacements{$1}/g replaces all matches (g modifier).
  • If you wanted more complex logic, you can use the e modifier 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., cat and cats). 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::Rewrite in 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

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
I like felines, canines, and avians.
STDERR
(empty)

Was this helpful?

Related Questions