2015-11-19 4 views
1

Учитывая строку, я хочу создать регулярное выражение, которое соответствует только недействительному, определенному символу, например. «точка с запятой», то есть , а не, найденная в скобках или круглых скобках. Я могу написать шаблон, который соответствует обратному случаю, но как я могу инвертировать (например, ^) шаблон?Регулярное выражение Python для поиска специальных символов между разделителями

EDIT: Следует отметить, что мне нужно общее решение, где между точкой с запятой и разделителем могут существовать символы длины n; не только совпадения нулевой ширины.

>>> invalid = '2#2;a,a [4,4;b/b]' 
>>> valid = '(2#2;a,a) [4,4;b/b]' 
>>> pattern = r'(\(.+?\;.+?\))|(\[.+?\;.+?\])'  # finds valid cases; want the opposite 

# Result 
>>>bool(re.findall(pattern, invalid))     
True            # overlooks the invalid subset '2;a' 
>>> not re.findall(pattern, valid) 
True 

# Desired result 
>>>bool(re.findall(pattern_inverse, invalid)) 
True 
>>> bool(re.findall(pattern_inverse, valid)) 
False 

ответ

2

Использование оператора чередования. Захваченный ; должен находиться за пределами этих скобок.

>>> import re 
>>> invalid = '2;a [4;b]' 
>>> valid = '(2;a) [4;b]' 
>>> pattern = r'(?:\([^()]*;[^()]*\)|\[[^\[\]]*\;[^\[\]]*\])|(;)' 
>>> re.findall(pattern, invalid) 
[';', ''] 
>>> re.findall(pattern, valid) 
['', ''] 
>>> any(re.findall(pattern, invalid)) 
True 
>>> any(re.findall(pattern, valid)) 
False 

ИЛИ

>>> pattern = r';(?![^()]*\)|[^\[\]]*\])' 
>>> any(re.findall(pattern, invalid)) 
True 
>>> any(re.findall(pattern, valid)) 
False 
>>> re.findall(pattern, invalid) 
[';'] 
>>> re.findall(pattern, valid) 
[] 
>>> 
+0

наклоняет вы просто вызываете 'любой (re.findall (...))', чтобы сделать такой же эффект, как список вашего компе –

+0

Ya, сделано спасибо .. –

+0

или ';?! ([^() ] * \) | [^ \ [\]] * \]) ' –

0

Вы можете использовать отрицательный предпросмотр и назад '. Для того, чтобы найти примеры ; не следует буква и квадратные скобки вы можете сделать это:

;(?![a-z]\]) 

Добавление назад 'дает вам что-то вроде этого:

(?<!\[[0-9]);(?![a-z]\]) 

Есть некоторые ограничения на то, что вы можете сделать в lookbehind - в частности, используя кванторы «*» или «+», невозможно.

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

(?<=^|\s)[^(\[]*;[^)\]]*(?=\s|$) 
+0

Ты прав. Lookarounds работают для этого конкретного случая, но мне нужно общее решение, которое не ограничено совпадением нулевой ширины. Я попытаюсь изменить вопрос, чтобы отразить эту потребность. Благодарю. – pylang

+1

@pylang - если вы можете сопоставить весь недействительный «2; a», вы можете обойти эту ситуацию, только требуя однократных обращений: (? <=^| \ S) [^ (\ [] *; [^) \]] * (? = \ s | $) –

+0

Спасибо за объяснение. Имеет смысл сопоставить все не разделители вокруг ';'. Тем не менее, последний пример, кажется, пропустит '(2; a' или' 2; a) 'cases, которые также не содержат'; '. Я не знаю, почему. – pylang