Silence
Silence

Reputation: 156

How to merge perl regexp's into one combined match

I have a Perl application that gets as input two regexp's.

Is it possible to merge the regexp's into one regexp in a way that a match can only happen if the two regexp conditions are met?

Example:

pattern1 = "^.*$"  
pattern2 = "^abc$"

Outcome should be: "^abc$"

I know there is a module called "Regexp::Assemble" but only allows me to combine the regexp's in a way that both regexp's can create a match.

Upvotes: 1

Views: 442

Answers (2)

Aran-Fey
Aran-Fey

Reputation: 43166

It's possible, but with a restriction. All you need to do is enclose one of the patterns in a lookahead assertion like so:

(?=pattern1)pattern2

This should work even if the patterns have inline modifiers ((?i) or similar), the first pattern's modifiers shouldn't carry over to the second pattern.

The only problem with this solution that I'm aware of are backreferences (\1, \2, etc). If there are capture groups in pattern1, then any backreferences in pattern2 will refer to the wrong group. For example:

pattern1 = "(a)b."
pattern2 = "a(b)\1"
text = "abb"

Both patterns would match abb, but the combined pattern (?=(a)b.)a(b)\1 would only match aba.

Upvotes: 1

Sobrique
Sobrique

Reputation: 53478

You cannot merge them into a single regex - that's a much more complicated thing than you might imagine. (Outside relatively trivial cases). regex is a programming language, and getting something to write it for you, is a non-trivial sort of a task.

But you can test multiple regexes quite handily.

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

my @conditions = ( qr/^.*$/, qr/[A-Z]+/, qr/123/, );

LINE: while (<DATA>) {
    foreach my $regex (@conditions) {
        next LINE unless m/$regex/;
    }
    print;
}

__DATA__
shouldn't match, non number
1234567
test123
Test123

For efficiency, you can also order the regexes so the most likely to fail come first.

Upvotes: 3

Related Questions