Pattern Matching & Substitution
Learn how to transform text in Perl with the s/// substitution operator, the /g and /i modifiers, and the tr/// transliteration operator.
Introduction
Matching text is useful, but Perl's real editing power comes from being able to transform text in place. The s/// operator finds a pattern and replaces it with something else, and tr/// translates individual characters. Together, these two operators handle the vast majority of real-world text-cleanup tasks.
- How s/// finds and replaces text.
- How the /g and /i modifiers change substitution behavior.
- How to reuse captured groups inside a replacement.
- How tr/// translates or counts individual characters.
The s/// Substitution Operator
The s/// operator has three parts separated by slashes: the pattern to search for, the replacement text, and optional modifiers after the final slash. By default it replaces only the first match it finds.
use strict;use warnings;
my $message = "I love Java programming!";
$message =~ s/Java/Perl/;print "$message\n";Click Run to see what this code prints.
Notice that s/// modifies the variable in place — it uses the same =~ binding operator, but instead of just testing the string, it rewrites it.
The /g Modifier
By default s/// stops after the first replacement. Adding the /g (global) modifier makes it replace every matching occurrence in the string, not just the first one.
use strict;use warnings;
my $csv = "apple,banana,cherry,date";
(my $tabbed = $csv) =~ s/,/\t/g;print "$tabbed\n";Click Run to see what this code prints.
(my $tabbed = $csv) =~ s/,/\t/g; is a common idiom: it copies $csv into a new variable first, then substitutes on the copy, leaving the original $csv untouched.
The /i Modifier
The /i modifier makes the match case-insensitive, so the pattern matches regardless of upper or lower case in the target string. It can be combined with /g in any order, such as /gi or /ig.
use strict;use warnings;
my $text = "Perl is great. PERL is powerful. perl is fun.";
(my $censored = $text) =~ s/perl/Rust/gi;print "$censored\n";Click Run to see what this code prints.
Substitution With Captures
Just like in a plain match, you can use parentheses in the pattern half of s/// to capture pieces of the matched text, then reference them in the replacement half using $1, $2, and so on. This lets you rearrange text, not just remove or replace it outright.
use strict;use warnings;
my $name = "Doe, John";
$name =~ s/(\w+), (\w+)/$2 $1/;print "$name\n";Click Run to see what this code prints.
This pattern captures the last name into $1 and the first name into $2, then the replacement swaps their order — a very common data-cleanup task in real-world Perl scripts.
The tr/// Operator
tr/// (also spelled y///) works differently from s///: instead of matching patterns, it translates individual characters one-for-one, based on two lists of characters you provide. It is much faster than a regex for simple character-level transformations, and it can also count characters without changing anything, if you pass no replacement list.
use strict;use warnings;
my $dna = "GATTACA";(my $complement = $dna) =~ tr/ACGT/TGCA/;print "Complement: $complement\n";
my $sentence = "Hello, World!";my $vowel_count = ($sentence =~ tr/aeiouAEIOU//);print "Vowel count: $vowel_count\n";Click Run to see what this code prints.
tr/// always returns the number of characters it matched (or replaced), which is why it doubles as a handy character-counting tool even when the replacement list is left empty.
Common Mistakes
- Forgetting /g and being surprised that only the first match got replaced.
- Assuming tr/// uses regular expressions — it does not; it only maps individual characters, not patterns.
- Using s/// without capturing when a swap or rearrangement is needed, then wondering where the original text went.
- Modifying a string with s/// or tr/// when you actually wanted to keep the original unchanged (remember the (my $copy = $original) =~ ... idiom).
- Mixing up the order of the two character lists in tr///, which silently produces the wrong mapping.
Best Practices
- Use /g whenever you intend to replace every occurrence, not just the first.
- Reach for tr/// instead of s/// for simple single-character replacements or counting — it is faster and clearer.
- Use named or numbered captures in s/// to rearrange or reformat text rather than deleting and retyping it manually.
- Combine /i with /g carefully, and test against mixed-case real data before shipping a substitution.
- Prefer the copy-then-substitute idiom when the original string still needs to be preserved elsewhere in the program.
Frequently Asked Questions
s/// performs full pattern-based find-and-replace using regular expressions. tr/// only translates individual characters based on two matching-position lists, with no regex support.
Yes, with the /r modifier: my $new = $original =~ s/foo/bar/r; leaves $original untouched and returns the modified copy instead.
s/// returns the number of substitutions it performed, so you can capture that directly: my $count = ($text =~ s/foo/bar/g);
Yes, y/// is simply an older, alternative spelling of the exact same operator as tr///.
Key Takeaways
- s/pattern/replacement/ finds and replaces text, modifying the string in place.
- The /g modifier replaces every match; /i makes the match case-insensitive.
- Captured groups in the pattern can be reused in the replacement as $1, $2, and so on.
- tr/// translates individual characters and can also count matching characters.
- The /r modifier returns a modified copy instead of changing the original string.
Summary
With matching and substitution covered, you now have Perl's full text-processing toolkit at your disposal. Next, you will shift focus to organizing code itself, starting with subroutines — how to package logic into reusable, named blocks.