Expressing AND, OR, and NOT in a Single Pattern
Problem
You have an existing program that accepts a pattern as an argument or input. It doesn’t allow you to add extra logic, like case insensitive options, ANDs, or NOTs. So you need to write a single pattern that matches either of two different patterns (the “or” case), both of two patterns (the “and” case), or that reverses the sense of the match (“not”).
This situation arises often in a configuration files, web forms, or command-line arguments. Imagine there’s a program that does this:
chomp($pattern = <CONFIG_FH>);
if ( $data =~ /$pattern/ ) { ..... }As the one maintaining the contents of CONFIG_FH, you need to convey Booleans through to the matching program through that one, measly pattern without explicit connectives.
Solution
True if either /ALPHA/ or
/BETA/ matches, like /ALPHA/
||
/BETA/:
/ALPHA|BETA/
True if both /ALPHA/ and /BETA/
match, but may overlap, meaning "BETALPHA" should
be okay, like /ALPHA/
&&
/BETA/:
/^(?=.*ALPHA)(?=.*BETA)/s
True if both /ALPHA/ and /BETA/
match, but may not overlap, meaning that
"BETALPHA" should fail:
/ALPHA.*BETA|BETA.*ALPHA/s
True if pattern /PAT/ does not match, like
$var
!~
/PAT/:
/^(?:(?!PAT).)*$/s
True if pattern BAD does not match, but pattern
GOOD does:
/(?=^(?:(?!BAD).)*$)GOOD/s
Discussion
When you’re writing a regular program and want to know if something doesn’t match, say one of:
if (!($string =~ /pattern/)) { something() } # ugly if ( $string !~ /pattern/) { something() } # preferred ...Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access