Calculating a negated character class

K

Klaus

Hello everybody,

I am trying to do a simple task: creating a regular expression with
qr{...}xms containing a simple character class. Then I can obviously
create the negated character class by putting a caret symbol at the
beginning inside the [...].

So far so good.

However, when I try (naively) to calculate the negated class from the
original character class, I get a compile time error:

Invalid [] range "x-i" in regex;
marked by <-- HERE in m/[^(?msx-i <-- HERE :[abc123])]/
at C:\test_regexp.pl line 6.

Here is my program
=========
use 5.012;
use warnings;

my $regexp_positive = qr{[abc123]}xms;
my $regexp_negated = qr{[^abc123]}xms;
my $calculated_negated = qr{[^$regexp_positive]}xms;

say "regexp_positive = $regexp_positive";
say "regexp_negated = $regexp_negated";
say "calculated_negated = $calculated_negated";
========

I understand that putting "(?msx-i" into a character class is not the
way forward, but how do I calculate the negated character class ?

Thanks in advance for your response.

-- Klaus
 
K

Klaus

Quoth Klaus said:
I understand that putting "(?msx-i" into a character class is not the
way forward, but how do I calculate the negated character class ?

    my $cclass          = "abc123";
    my $regexp_positive = qr/[$cclass]/xms;
    my $regexp_negated  = qr/[^$cclass]/xms;

Thanks for your reply. I can see clearer now.

So the way forward is isolating the class from the regexp construct.

Here is an updated version of my original program and it works!

=============
use 5.012;
use warnings;

my $regexp1_orig = qr{[abc123]}xms;
my $regexp2_orig = qr{[^def456]}xms;

say "regexp1_orig = $regexp1_orig";
say "regexp2_orig = $regexp2_orig";

my $regexp1_negated = negated($regexp1_orig);
my $regexp2_negated = negated($regexp2_orig);

say "regexp1_negated = $regexp1_negated";
say "regexp2_negated = $regexp2_negated";

sub negated {
my ($caret, $class) = $_[0] =~ m{\A \(\? [\w\-]* : \[ (\^?) (.*?)
\]\) \z}xms
or die "Can't parse regexp: $_[0]";

my $neg_caret = $caret eq '^' ? '' : '^';
my $neg_regexp = qr{[$neg_caret$class]}xms;

return $neg_regexp;
}
=============

The output is:

regexp1_orig = (?msx-i:[abc123])
regexp2_orig = (?msx-i:[^def456])
regexp1_negated = (?msx-i:[^abc123])
regexp2_negated = (?msx-i:[def456])
 
K

Klaus

Quoth Klaus said:
sub negated {
    my ($caret, $class) = $_[0] =~ m{\A \(\? [\w\-]* : \[ (\^?)(.*?)
\]\) \z}xms

In 5.14 the stringification syntax for qrs has changed. It now looks
like

    (?^umsx:[abc123])

This was done to allow for future extensions to the set of /x flags. You
can either adjust your code to take account of this, or, better, use the
regexp_pattern function exported by the re module:

    use re qw/regexp_pattern/;

    my ($pattern, $flags) = regexp_pattern $_[0];
    my ($caret, $class) = $pattern =~ /\A \[ (\^?) (.*?) \] \z/xms
        or die ...;

Thank you very much for this information, I wasn't aware that the
stringification syntax differs between different versions perl.

I will use re qw/regexp_pattern/ as follows:

==============
use 5.012;
use warnings;

use re qw/regexp_pattern/;

my $regexp1_orig = qr{[abc123]}xms;
my $regexp2_orig = qr{[^def456]}xms;

say "regexp1_orig = $regexp1_orig";
say "regexp2_orig = $regexp2_orig";

my $regexp1_negated = negated($regexp1_orig);
my $regexp2_negated = negated($regexp2_orig);

say "regexp1_negated = $regexp1_negated";
say "regexp2_negated = $regexp2_negated";

sub negated {
my ($pattern, $flags) = regexp_pattern($_[0]);
my ($caret, $class) =
$pattern =~ m{\A \[ (\^?) (.*?) \] \z}xms
or die "Can't parse regexp: $_[0]";

my $neg_caret = $caret eq '^' ? '' : '^';
my $neg_regexp = qr{[$neg_caret$class]}xms;

return $neg_regexp;
}
==============
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top