regex intermediate

How to use non-capturing groups (?:...) in Perl regex?

Question

How to use non-capturing groups (?:...) in Perl regex?

In Perl regular expressions, parentheses () are used to create capturing groups, which capture parts of the matched string for later use, typically accessible via $1, $2, and so forth. However, there are situations where you want to group parts of a pattern, but without capturing that part for back-references or extraction—this is where non-capturing groups come in.

What are Non-Capturing Groups?

A non-capturing group groups the regex tokens just like normal parentheses but does not save the matched substring in a capture variable. This helps improve regex performance slightly and keeps the list of capture variables clean.

Syntax: (?:pattern) where pattern is grouped but not captured.

Why Use Non-Capturing Groups?

  • Avoid unnecessary captures: If you group solely to apply an operator like ?, *, or + to multiple tokens, but don't need the data captured, use non-capturing groups. This prevents cluttering $1, $2, etc.
  • Improve readability: It clearly indicates intent—group without capturing.
  • Performance: Slightly faster since Perl doesn't have to save matched substring references.

Example: Using Non-Capturing Groups in Perl

Suppose you want to match either "cat" or "dog" followed by "s" to capture plural animals, but you only want to capture "cats" or "dogs" as a whole, not separately the animal word:

use strict;
use warnings;

my $text = "I have cats and dogs.";

if ($text =~ /(?:cat|dog)s/) {
    print "Matched plural animal: $&\n";
}

# But if you want to capture just the animal part, use capturing groups
if ($text =~ /(cat|dog)s/) {
    print "Captured animal: $1\n";
}

Here, the first regex /(?:cat|dog)s/ matches either "cat" or "dog" followed by s but does not capture the part inside the group (no $1 defined). The special variable $& contains the entire matched string.

The second regex /(cat|dog)s/ captures "cat" or "dog" in $1—which can be useful if you need to extract just the animal name.

Key Points & Gotchas

  • The non-capturing syntax (?:...) was introduced in Perl 5.005 and is available in all modern versions.
  • Using too many capturing groups can complicate code and reduce performance.
  • If you don't need to back-reference or access a group's content, prefer non-capturing groups.
  • Beware of mistakenly using parentheses without ?: when you mean non-capturing group; this can lead to unexpected $1, $2 captures.

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
Matched plural animal: cats
Captured animal: cat
STDERR
(empty)

Was this helpful?

Related Questions