2011-02-07 4 views
7

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

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) 

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

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

+2

Не можете ли вы использовать правильный парсер C#? – Gumbo

+2

В начале я сказал: «Я занимаюсь гимнастикой регулярного выражения. Я поставил перед собой задачу поиска C#» ... –

+0

Это как смотреть футбол и думать «это как заниматься гимнастикой»? :-) – xanatos

ответ

11

I любовь регулярных выражений гимнастика! Вот прокомментировал 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)""" 
+0

И если вы хотите, чтобы он работал с отрицательным условным тестом, например. 'X! = Null', просто измените каждый:' == 'to:' [! =] = ' – ridgerunner

+0

Очень красиво сделано и хорошее объяснение. +1. Я бы включил обычное оговорку о регулярном выражении, не будучи на 100% надежным для синтаксического анализа C#. –

2

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

\bas\b(?![\s\S]{1,150}==\s*null\b) 
+0

Я не могу заставить вашу идею работать, она по-прежнему включает второй пример выше в моих результатах поиска. –

+0

Это регулярное выражение: '\ bas \ b (?! [\ S \ S] {1,150} == \ s * null \ b)' довольно близко, но не соответствует второй AS в первом наборе "должно совпадать "тестовые данные. – ridgerunner

+0

@ridgerunner это работает для вас с Python? У меня нет установки C# для тестирования. – robert

2

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

\b(\w+)\b\W*=\W*\w*\W*\bas\b[\s\S]{1,150}(?!\b\1\b\W*==\W*\bnull\b) 
2

Вопрос не ясен. Чего вы хотите ТОЧНО? Я сожалею, но я до сих пор не понимаю, прочитав вопрос и комментарии много раз.

.

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

.

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

Или может гетерогенная линия быть МЕЖДУ блоком и линией if(... == ...) без остановки согласования?

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

.

Есть ли линия if(... == null) ПОСЛЕ if(... == ...) линия остановки матча или нет?

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

.

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

Это в 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 
----------------------------------------- 
>>> 
+0

+1 Я согласен, что вопрос довольно расплывчатый. Большинство людей не понимают, что хороший вопрос о регулярном выражении должен быть четко прописан. – ridgerunner

2

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

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

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

Regex's действительно не подходит для не что-то подходящее. В этом случае вам лучше пытаться соответствовать «как» присвоение с «если == NULL» проверить в пределах 150 символов:

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

, а затем отрицающих чек: if (!regex.match(text)) ...

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

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

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

Имейте в виду, что \s, вероятно, поймать пробелы, которые не являются «действительные пробелы».Он определяется как [\f\n\r\t\v\x85\p{Z}], где \p{Z} является Unicode Characters in the 'Separator, Space' Category plus Unicode Characters in the 'Separator, Line' Category plus Unicode Characters in the 'Separator, Paragraph' Category.

 Смежные вопросы

  • Нет связанных вопросов^_^