Регулярные выражения отрицательный взгляд - PullRequest
7 голосов
/ 07 февраля 2011

Я занимаюсь гимнастикой с регулярными выражениями.Я поставил перед собой задачу поиска кода на C #, где используется оператор as, за которым не следует нулевая проверка в разумных пределах пространства.Теперь я не хочу разбирать код C #.Например, я хочу захватывать фрагменты кода, такие как

    var x1 = x as SimpleRes;
    var y1 = y as SimpleRes;
    if(x1.a == y1.a)

, но не захватывать

    var x1 = x as SimpleRes;
    var y1 = y as SimpleRes;
    if(x1 == null)

, ни в коем случае

    var x1 = x as SimpleRes;
    var y1 = y as SimpleRes;
    if(somethingunrelated == null) {...}
    if(x1.a == y1.a)

Таким образом, любая случайная нулевая проверкабудет считаться "хорошим чеком" и, следовательно, не найден.

Вопрос в следующем: Как мне сопоставить что-либо, при этом убедившись, что что-то еще не найдено в его окружении.

Я пробовал наивный подход, ища «какзатем делает отрицательный прогноз в пределах 150 символов.

\bas\b.{1,150}(?!\b==\s*null\b)

Вышеуказанное регулярное выражение, к сожалению, соответствует всем приведенным выше примерам.Моя интуиция говорит мне, что проблема в том, что если смотреть в будущее, а затем делать отрицательный прогноз, можно найти много ситуаций, когда он не найдет «== ноль».

Если я попытаюсь отрицать все выражение целиком, то это тоже не поможет, в этом случае будет соответствовать большинство кодов C # вокруг.

Ответы [ 6 ]

11 голосов
/ 17 марта 2011

Я люблю Регулярная гимнастика! Вот прокомментированное регулярное выражение PHP:

$re = '/# Find all AS, (but not preceding a XX == null).
    \bas\b               # Match "as"
    (?=                  # But only if...
      (?:                # there exist from 1-150
        [\S\s]           # chars, each of which
        (?!==\s*null)    # are NOT preceding "=NULL"
      ){1,150}?          # (and do this lazily)
      (?:                # We are done when either
        (?=              # we have reached
          ==\s*(?!null)  # a non NULL conditional
        )                #
      | $                # or the end of string.
      )
    )/ix'

А вот и в стиле Javascript:

re = /\bas\b(?=(?:[\S\s](?!==\s*null)){1,150}?(?:(?===\s*(?!null))|$))/ig;

Это заставило мою голову немного болеть ...

Вот данные теста, которые я использую:

text = r"""    var x1 = x as SimpleRes;
    var y1 = y as SimpleRes;
    if(x1.a == y1.a)

however, not capture
    var x1 = x as SimpleRes;
    var y1 = y as SimpleRes;
    if(x1 == null)

nor for that matter
    var x1 = x as SimpleRes;
    var y1 = y as SimpleRes;
    if(somethingunrelated == null) {...}
    if(x1.a == y1.a)"""
2 голосов
/ 22 марта 2011

Позвольте мне попытаться переопределить вашу проблему:

  1. Ищите назначение «как» - вам, вероятно, нужен лучший регулярный оператор для поиска реальных назначений, и вы можете захотеть сохранить назначенное выражение, нодавайте использовать "\ bas \ b" сейчас
  2. Если вы видите if (... == null) в пределах 150 символов, не сопоставляйте
  3. Если вы не видите if (... == null) в пределах 150 символов, match

Ваше выражение \bas\b.{1,150}(?!\b==\s*null\b) не будет работать из-за негативного просмотра.Регулярное выражение всегда может пропустить вперед или позади одной буквы, чтобы избежать этого негативного прогнозирования, и вы в конечном итоге сопоставляете, даже когда там есть if (... == null).

Регулярные выражения действительно не хороши в не соответствует что-то.В этом случае лучше попытаться сопоставить назначение «как» с проверкой «if == null» в пределах 150 символов:

\bas\b.{1,150}\b==\s*null\b

, а затем отменить проверку: if (!regex.match(text)) ...

2 голосов
/ 17 марта 2011

Вопрос не ясен.Что вы хотите точно?Я сожалею, но все еще не понимаю, прочитав вопрос и комментарии несколько раз.

.

Должен ли код быть на C #?В питоне?Другой ?Нет никаких указаний относительно этой точки

.

Требуется ли сопоставление, только если строка if(... == ...) следует за блоком из var ... = ... строк?

Или можетгетерогенной ли строкой между блоком и линией if(... == ...) без остановки сопоставления?

Мой код принимает второй параметр за истину.

.

Имеет ли if(... == null)line ПОСЛЕ a if(... == ...) line остановка совпадения или нет?

Невозможно понять, да это или нет, я определил два регулярных выражения, чтобы поймать эти два параметра.

Надеюсь, мой код будет достаточно понятным и отвечающим вашей озабоченности.

Он написан на Python

import re

ch1 ='''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(x1.a == y1.a)
1618987987849891
'''

ch2 ='''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
uydtdrdutdutrr
if(x1.a == y1.a)
3213546878'''

ch3='''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(x1 == null)
165478964654456454'''

ch4='''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
hgyrtdduihudgug
if(x1 == null)
165489746+54646544'''

ch5='''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(somethingunrelated == null ) {...}
if(x1.a == y1.a)
1354687897'''

ch6='''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
ifughobviudyhogiuvyhoiuhoiv
if(somethingunrelated == null ) {...}
if(x1.a == y1.a)
2468748874897498749874897'''

ch7 = '''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(x1.a == y1.a)
iufxresguygo
liygcygfuihoiuguyg
if(somethingunrelated == null ) {...}
oufxsyrtuy
'''

ch8 = '''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
tfsezfuytfyfy
if(x1.a == y1.a)
iufxresguygo
liygcygfuihoiuguyg
if(somethingunrelated == null ) {...}
oufxsyrtuy
'''

ch9 = '''kutgdfxfovuyfuuff
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
tfsezfuytfyfy
if(x1.a == y1.a)
if(somethingunrelated == null ) {...}
oufxsyrtuy
'''

pat1 = re.compile(('('
                   '(^var +\S+ *= *\S+ +as .+[\r\n]+)+?'
                   '([\s\S](?!==\s*null\\b))*?'
                   '^if *\( *[^\s=]+ *==(?!\s*null).+$'
                   ')'
                   ),
                  re.MULTILINE)

pat2 = re.compile(('('
                   '(^var +\S+ *= *\S+ +as .+[\r\n]+)+?'
                   '([\s\S](?!==\s*null\\b))*?'
                   '^if *\( *[^\s=]+ *==(?!\s*null).+$'
                   ')'
                   '(?![\s\S]{0,150}==)'
                   ),
                  re.MULTILINE)


for ch in (ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8,ch9):
    print pat1.search(ch).group() if pat1.search(ch) else pat1.search(ch)
    print
    print pat2.search(ch).group() if pat2.search(ch) else pat2.search(ch)
    print '-----------------------------------------'

Результат

>>> 
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(x1.a == y1.a)

var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(x1.a == y1.a)
-----------------------------------------
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
uydtdrdutdutrr
if(x1.a == y1.a)

var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
uydtdrdutdutrr
if(x1.a == y1.a)
-----------------------------------------
None

None
-----------------------------------------
None

None
-----------------------------------------
None

None
-----------------------------------------
None

None
-----------------------------------------
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
if(x1.a == y1.a)

None
-----------------------------------------
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
tfsezfuytfyfy
if(x1.a == y1.a)

None
-----------------------------------------
var x1 = x as SimpleRes;
var y1 = y as SimpleRes;
tfsezfuytfyfy
if(x1.a == y1.a)

None
-----------------------------------------
>>> 
2 голосов
/ 17 марта 2011

Я думаю, что это поможет поместить имя переменной в (), чтобы вы могли использовать его в качестве обратной ссылки. Что-то вроде следующего,

\b(\w+)\b\W*=\W*\w*\W*\bas\b[\s\S]{1,150}(?!\b\1\b\W*==\W*\bnull\b)
2 голосов
/ 07 февраля 2011

Поместите .{1,150} в поле зрения и замените . на \s\S (в общем случае . не соответствует символам новой строки).Кроме того, \b может вводить в заблуждение вблизи ==.

\bas\b(?![\s\S]{1,150}==\s*null\b)
1 голос
/ 23 марта 2011
(?s:\s+as\s+(?!.{0,150}==\s*null\b))

Я активирую опцию SingleLine с помощью ?s:.Вы можете поставить его в настройках своего регулярного выражения, если хотите.Я добавлю, что я ставлю \s вокруг as, потому что я думаю, что только пробелы "законны" вокруг as.Вы, вероятно, можете поставить \b как

(?s:\b+as\b(?!.{0,150}==\s*null\b))

Имейте в виду, что \s, вероятно, будет ловить пробелы, которые не являются "допустимыми пробелами".Он определяется как [\f\n\r\t\v\x85\p{Z}], где \p{Z} - это Юникод-символы в категории «Разделитель, пробел» плюс Юникод-символы в категории «Разделитель, строка» плюс Юникод-символыв категории «Разделитель, абзац» .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...