regex advanced

How to use negative lookbehind (?<!...) in Perl regex?

Question

How to use negative lookbehind (?<!...) in Perl regex?

In Perl regular expressions, negative lookbehind (?<!...) lets you match a pattern only if it is not immediately preceded by a specific substring. It's a zero-width assertion that checks context without consuming characters.

What is Negative Lookbehind?

Negative lookbehind has the form (?<!pattern). It asserts that the current position is not immediately preceded by pattern. For example, /(?<!\d)foo/ matches "foo" only if it is not preceded by a digit.

Perl Version Requirements

  • Negative lookbehind is supported from Perl 5.005 onwards (widely available).
  • Lookbehind patterns must be fixed-width; variable-length quantifiers like * or + are not allowed inside lookbehinds.

Runnable Example

This script demonstrates finding "foo" only when not preceded by "bar":

#!/usr/bin/perl
use strict;
use warnings;

my $text = "barfoo bazfoo quxfoo";

while ($text =~ /(?

Explanation:

  • The regex /(?<!bar)foo/g matches "foo" unless immediately preceded by "bar".
  • In "barfoo bazfoo quxfoo", the first "foo" follows "bar" so it's skipped.
  • The "foo" in "bazfoo" and "quxfoo" match successfully.
  • The substitution example replaces only the matching instances with "FOO".

Common Gotchas

  • Fixed-width limitation: Patterns like (?<!.*bar) won't work; use (?<!bar) or (?<!barr) with fixed length.
  • Zero-width assertion: Lookbehind doesn't consume characters, only checks the condition.
  • Character classes work: (?<![0-9]) checks for any digit before the match position.

Summary

Negative lookbehind (?<!pattern) is essential for context-aware pattern matching in Perl. It ensures a pattern matches only when not preceded by specific text, making it invaluable for parsing and text processing tasks.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 6ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Found 'foo' at position 10
Found 'foo' at position 17

Demonstration with substitution:
Result: barfoo bazFOO quxFOO
STDERR
(empty)

Was this helpful?

Related Questions