Reputation: 11
I got this regex code:
((\w)(\w)\3\2)
It matches everything that contains something like anna, otto, xyyx ...
But I want to match everything that does NOT contain such a pattern. How can i do that?
Upvotes: 1
Views: 916
Reputation: 34307
Initially I thought this kind of does what you are asking. But for the reasons raised by @WiktorStribiżew below it does not work. In particular test strings such as AAAB and ABBC are supposed to match the below but do not
^((\w)(\w)(?!\3)(?!\2))
My second thought is to use
^((\w)(\w)(?!\3\2))
And this does seem to work.
New test program. This generates all possible strings from AAAA to ZZZZ. Then a non regexp check is used to test if each string should match or not. Finally, each string is checked for compliance against both the positive
$findrepeats, ^((\w)(\w)(\3)(\2))
matches abba
and the negative
$repeatnomatch ^((\w)(\w)(?!\3)(?!\2))
matches ab[not b][not a]
use strict;
use warnings;
my @fourchar=('AAAA'..'ZZZZ');
my @norepeats=();
my @hasrepeats=();
for my $pattern ('AAAA' .. 'ZZZZ') {
if (checkstring($pattern)) {
push @hasrepeats, $pattern;
} else {
push @norepeats, $pattern;
}
}
print scalar @hasrepeats, " strings with repeated abba\n";
print scalar @norepeats, " strings with ab[not b][not a]\n";
my $findsrepeats=qr/^((\w)(\w)(\3)(\2))/;
my $repeatnomatch=qr/^((\w)(\w)(?!\3\2))/;
for my $example (@hasrepeats) {
die $example if (not($example=~$findsrepeats));
die $example if ($example=~$repeatnomatch);
}
for my $example (@norepeats) {
die $example if (not($example=~$repeatnomatch));
die $example if ($example=~$findsrepeats);
}
print "pass\n";
sub checkstring {
my $s=shift;
my @element=split(//,$s);
return ($element[0] eq $element[3] &&
$element[1] eq $element[2]);
}
Running the above perl program should produce this output
$ perl nr3.pl
676 strings with repeated abba
456300 strings with ab[not b][not a]
pass
Upvotes: 0