Perl qr//
last modified October 20, 2026
The qr// operator quotes and compiles a regular expression and
returns it as an object. Instead of repeating long patterns, you give them
names, combine them, and pass them around like any other value. This turns
complex regular expressions into readable building blocks.
Creating a compiled regex
The qr// operator compiles a pattern into a regex object without
matching anything. The object can be stored in a variable, passed to subroutines
and used wherever a pattern is expected.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my $digits = qr/\d+/;
say "ref type: ", ref $digits;
say "stringified: $digits";
for my $s ('abc 123', 'no numbers') {
if ($s =~ $digits) {
say "'$s' matches, found: $&";
} else {
say "'$s' does not match";
}
}
my $ci = qr/perl/i;
say "case-insensitive: ", ('I love PERL' =~ $ci ? 'yes' : 'no');
The type of the object, as reported by ref, is Regexp.
Printing it shows the pattern together with its flags, in the form
(?^u:...): the caret resets the flags to the defaults and the
u comes from use v5.34, which enables Unicode string
semantics. The object can be used directly on the right side of =~.
Flags given to qr, such as /i, are stored in the
object.
$ perl basic.pl ref type: Regexp stringified: (?^u:\d+) 'abc 123' matches, found: 123 'no numbers' does not match case-insensitive: yes
Composing patterns
Regex objects can be interpolated into other patterns. Each one keeps its own flags, so small named pieces can be combined into a larger expression that stays readable.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my $word = qr/[a-z]+/i;
my $num = qr/\d+/;
my $line = qr/^($word)\s*=\s*($num)$/;
for my $s ('width = 80', 'Height=25', 'depth = x') {
if (my ($k, $v) = $s =~ $line) {
say "$k => $v";
} else {
say "no match: $s";
}
}
my $with_flag = qr/hello/i;
say "embedded flags: ", qr/$with_flag world/;
say "'HELLO world' matches: ", ('HELLO world' =~ /^$with_flag world$/ ? 'yes' : 'no');
say "'HELLO WORLD' matches: ", ('HELLO WORLD' =~ /^$with_flag world$/ ? 'yes' : 'no');
The $line pattern is built from $word and
$num, and the captured groups are returned in list context. The
last lines show that the embedded flags travel with the object: the interpolated
$with_flag keeps /i for the word hello,
but not for the literal text outside it, so HELLO WORLD fails.
$ perl compose.pl width => 80 Height => 25 no match: depth = x embedded flags: (?^u:(?^ui:hello) world) 'HELLO world' matches: yes 'HELLO WORLD' matches: no
Building a larger pattern: IPv4
Composition pays off with complicated patterns. An IPv4 address is made of four decimal octets, and defining one octet once avoids repeating the long alternation.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my $octet = qr/(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)/;
my $ipv4 = qr/^$octet(?:\.$octet){3}$/;
for my $ip ('192.168.1.10', '255.255.255.255', '256.1.1.1', '1.2.3', '10.0.0.01') {
printf "%-16s %s\n", $ip, $ip =~ $ipv4 ? 'valid' : 'invalid';
}
The $octet pattern accepts 0-255 through four alternatives, and
non-capturing groups (?:...) keep it from creating captures. The
address pattern repeats the octet three more times after a dot. The out-of-range
value and the incomplete address are rejected, and so is the octet with a
leading zero.
$ perl ipv4.pl 192.168.1.10 valid 255.255.255.255 valid 256.1.1.1 invalid 1.2.3 invalid 10.0.0.01 invalid
Patterns from word lists
A list of words can be turned into an alternation. Every word must go through
quotemeta to neutralize special characters, and sorting by length
makes the longest word win.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my @keywords = ('if', 'else', 'while', 'for.each');
my $alt = join '|', map { quotemeta } sort { length $b <=> length $a } @keywords;
my $re = qr/\b(?:$alt)\b/;
say "pattern: $re";
my $code = 'if x then for.each y else while z; foreach';
my @found = $code =~ /($re)/g;
say "found: @found";
(my $marked = $code) =~ s/($re)/[$1]/g;
say $marked;
The join call produces the alternation, and qr wraps
it in word boundaries. The same object is used for a global match in list
context and in a substitution. The text foreach is not marked,
since it is not an exact keyword. The dot in for.each is matched
literally because of quotemeta.
$ perl words.pl pattern: (?^u:\b(?:for\.each|while|else|if)\b) found: if for.each else while [if] x then [for.each] y [else] [while] z; foreach
Tables of patterns
Regex objects are ordinary scalars, so they can be kept in arrays and hashes. A
table of patterns is a clean replacement for a long chain of if and
elsif statements.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my @rules = (
[ integer => qr/^[+-]?\d+$/ ],
[ float => qr/^[+-]?\d*\.\d+(?:[eE][+-]?\d+)?$/ ],
[ word => qr/^\w+$/ ],
[ blank => qr/^\s*$/ ],
);
for my $input ('42', '-3.14', '.5e-2', 'hello', ' ', 'a b') {
my ($type) = map { $_->[0] } grep { $input =~ $_->[1] } @rules;
say sprintf "%-8s => %s", "'$input'", $type // 'unknown';
}
Each rule holds a name and a compiled pattern. The grep keeps the
rules that match the input and map extracts the name; the first one
is taken. The order matters here, since the word pattern would also
accept digits, and the integer rule has to come first. Inputs matched by no rule
are reported as unknown.
$ perl table.pl '42' => integer '-3.14' => float '.5e-2' => float 'hello' => word ' ' => blank 'a b' => unknown
Reusing a regex
A regex object works with split, grep,
s/// and hash storage alike. Compiling once and reusing it also
avoids recompiling inside loops.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my $sep = qr/\s*[,;]\s*/;
my @fields = split $sep, 'a , b;c ;d';
say join '|', @fields;
my @items = grep { $_ =~ qr/^\d+$/ } qw(10 abc 20 3x 30);
say "@items";
my $ws = qr/\s+/;
(my $clean = "too much \t space") =~ s/$ws/ /g;
say $clean;
my %compiled = map { $_ => qr/\b\Q$_\E\b/i } qw(perl ruby go);
for my $text ('I use Perl and Go', 'Ruby rocks') {
my @hits = grep { $text =~ $compiled{$_} } sort keys %compiled;
say "'$text' mentions: @hits";
}
The same style of object serves as separator in split, as filter in
grep, and as pattern in a substitution. The last example
precompiles one case-insensitive pattern per language into a hash;
\Q...\E quotes any special characters in the key, and the loop then
only looks the patterns up.
$ perl reuse.pl a|b|c|d 10 20 30 too much space 'I use Perl and Go' mentions: go perl 'Ruby rocks' mentions: ruby
Best Practices
- Name the pieces: small
qr//objects such as$octetmake big patterns readable. - Quote user data: pass words from outside through
quotemetaor\Q...\Ebefore building a pattern. - Use /x for long patterns: whitespace and comments in a
qr//xobject explain the intent. - Compile once: create the object outside the loop and reuse it.
- Mind flags: interpolated objects keep their own flags; they do not inherit those of the outer pattern.
In this article we have covered the qr// operator: creating regex
objects, composing larger patterns, building alternations from word lists,
tables of patterns, and reusing a compiled regex.
Source
perlop: Regexp Quote-Like Operators
Author
List all Perl tutorials.