1

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?

serenesat
  • 4,611
  • 10
  • 37
  • 53

2 Answers2

1

This issue has already been raised on this SO post. You should try this :

^((?!(\w)(\w)\3\2).)*$
Community
  • 1
  • 1
cromod
  • 1,721
  • 13
  • 26
  • This only matches a whole line/string that does not contain the pattern but not anything that does not match the pattern. – Wiktor Stribiżew Feb 03 '16 at 19:36
  • 1
    The OP didn't ask for _anything that does not match the pattern_, but for _everything that does not **contain** a pattern._ The sensible interpretation of _thing_ in this case is _line_, thus this answer is perfectly right. – Armali Apr 05 '16 at 11:45
0

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
Vorsprung
  • 32,923
  • 5
  • 39
  • 63
  • This is incorrect. When do you think `(?!\2)` is executed? – Wiktor Stribiżew Feb 03 '16 at 19:35
  • @WiktorStribiżew I would guess it is evaluated left to right, so the capture groups are set first and then the negative look-ahead assertions are done after this. The test program seems to work as I'd expect, so if you could give me strings that give false negatives or positives it might help me to understand this further. Thanks – Vorsprung Feb 04 '16 at 09:10
  • Your assumptions are correct but if you plan to match `ab[not-b][not-a]`, this regex won't do, because lookaheads are executed at the same place, after `b`. `(?!\2)` checks if the character after `b` is not `a`. The fourth character can be any. – Wiktor Stribiżew Feb 04 '16 at 10:05
  • @WiktorStribiżew ok I've managed to figure out how to replicate what you are saying. If I feed a string like "AAAB" ``^((\w)(\w)(?!\3)(?!\2))`` does not match but it should. I am rewriting the answer – Vorsprung Feb 04 '16 at 13:16