Regex соответствует всему, кроме слова - PullRequest
1 голос
/ 01 июля 2019

Все QA о совпадают с чем-то, кроме слова с отрицательным прогнозом, который я обнаружил, подразумевает строки начало / конец (^ $). Но я не могу понять, как мне сопоставить все (любой символ, например .*), кроме слова перед каким-либо другим словом в середине обработанного текста.

Я должен соответствовать ABC внутри <tag></tag>:

...<tag>a a.__aABC&*</tag>aaa<tag>ffff</tag>...

но не снаружи (ложно-положительный):

...<tag>a a.__a&*</tag>ABC<tag>ffff</tag>...

Так что я думаю, что я должен исключить закрытие тега (</tag>) до ABC. Я попробовал:

<tag>(?!<\/tag>)ABC.*?<\/tag>

но таким образом он не позволяет сопоставлять .*, за исключением </tag> до ABC. Как я могу это реализовать?

Полезные ссылки:

1 , 2 .

1 Ответ

2 голосов
/ 08 июля 2019

Поскольку вы используете один из Perl / PCRE, самый быстрый способ сделать это так:

/(?s)<tag>(?:<\/tag>(*SKIP)(*FAIL)|.)*?ABC.*?<\/tag>/

https://regex101.com/r/AoiwIH/1

Расширенный

 (?s)
 <tag>  
 (?:
      </tag>
      (*SKIP) (*FAIL) 
   |  
      . 
 )*?
 ABC
 .*? 
 </tag>

Сравнительный тест по сравнению с методом

Regex1:   (?s)<tag>(?:</tag>(*SKIP)(*FAIL)|.)*?ABC.*?</tag>
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   1
Elapsed Time:    0.25 s,   254.91 ms,   254905 µs
Matches per sec:   196,151


Regex2:   (?s)<tag>(?:(?!</tag>).)*?ABC.*?</tag>
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   1
Elapsed Time:    0.33 s,   329.10 ms,   329095 µs
Matches per sec:   151,931
...