2016-03-02 2 views
1

Почему регулярное выражение:Почему [^ A] не работает?

changes\s*=\s*[^A].* 

матчи

changes = AssignDictionary(out 

То, что я хочу найти нет слов, которые начинаются с символа "A" ([^A]) после пространств (\s*), и это предполагает не чтобы соответствовать этой строке ... что я делаю неправильно?

+2

'' '' (два пространства) соответствуют '\ s * [^ A]' (любое количество пробелов, за которым следует что-то не A, пробел не равен A) – deceze

+2

(и даже если бы было только одно место, оно все равно соответствовало бы ...) –

+0

Указанный на другом представлении: он избежит '= A' без пробела между = и A – Tensibai

ответ

5

[^A] не работает из-за обратной связи. \s* соответствует нулевому или более пробелам, а затем возвращается назад, для размещения non-A. Поскольку после = есть два пробела, второе пространство совпадает с [^A] -> есть совпадение.

См Шаг 12 & 13 (regex demo):

enter image description here

Если вы хотите, чтобы провалить матч, когда есть A после =, вам нужен отрицательный предпросмотр:

changes\s*=(?!\s*A)\s*.* 
      ^^^^^^^^ 

См. another demo

Или другое изменение PCRE: changes\s*=\s*+(?!A).* (проверьте, не является ли символ A после пробелов после =).

Если движок регулярных выражений поддерживает атомные группы или притяжательные кванторы, вы можете сделать вашу регулярное выражение работу путем предотвращения возвратов в \s* конструкции:

changes\s*=\s*+[^A].* 
      ^^ (possessive quantifier) 

changes\s*=(?>\s*)[^A]\s*.* 
      ^^ ^- atomic group 

И в случае, если ваш двигатель не поддерживает атомные группы, ни притяжательные кванторы, вы можете отключить возвраты с помощью комбинации группы захвата/обратной ссылки (для эмуляции атомной группы):

changes\s*=(?=(\s*))\1[^A].* 

См this demo.

Тем не менее, первое решение с lookahead предпочтительнее, поскольку оно кажется самым универсальным. Самый быстрый вид - тот, у кого есть притяжательный квантификатор.

+1

Я полагаю, что работа с' \ b' может также решить проблему. – deceze

+0

Хм, не знаю, будет ли работать '\ b', но я только что проверил, и исходное регулярное выражение будет работать, если мы предотвратим обратную трассировку с помощью атомной группы или обладающего квантификатором. –

+0

Для записи '\ s * \ b [^ A]', похоже, работает, и IMO намного проще. – deceze

0

Это также можно получить с помощью обычного регулярного выражения. Просто укажите, что не является допустимым символом после произвольного количества пробелов перед «не А». Как вы указали, это: не A, но, конечно, также «не пространство». В противном случае возврат в исходное положение позволит пробелу, предшествующему позиции A в положении tat, до , будет соответствовать «не-А» и победить ваши намерения.

Использование изменений \ s * = \ s * [^ A \ s]. * будет соответствовать любому, у которого нет пробела A или пробела после пробелов, следующих за значком равенства (и продлить соответствие до конца