2015-04-29 1 views
4

Как я могу сопоставить r '\ a' в Python с использованием утверждения lookbehind?
На самом деле, мне нужно, чтобы соответствовать строки C++ как "a \" b" иКак использовать '' в правильном выражении утверждения python (? <= \) для соответствия строкам с цитированием C++

"str begin \ 
end" 

Я пробовал:

>>> res = re.compile('(?<=\)a') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/re.py", line 190, in compile 
    return _compile(pattern, flags) 
    File "/usr/lib/python2.7/re.py", line 244, in _compile 
    raise error, v # invalid expression 

>>> res = re.compile('(?<=\\)a') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/re.py", line 190, in compile 
    return _compile(pattern, flags) 
    File "/usr/lib/python2.7/re.py", line 244, in _compile 
    raise error, v # invalid expression 
sre_constants.error: unbalanced parenthesis 

>>> res = re.compile('(?<=\\\)a') 
>>> ms = res.match(r'\a') 
>>> ms is None 
True 

Реальный пример:
Когда я parcing "my s\"tr"; 5; как ms = res.match(r'"my s\"tr"; 5;'), ожидаемый выход : "my s\"tr"

Ответ
Наконец stribizhev предоставил решение. Я думал, что мое первоначальное регулярное выражение менее вычислительно дорогой и единственный вопрос заключается в том, что она должна быть объявлена ​​с использованием сырой строки:

>>> res = re.compile(r'"([^\n"]|(?<=\\)["\n])*"', re.UNICODE) 
>>> ms = res.match(r'"my s\"tr"; 5;') 
>>> print ms.group() 
"my s\"tr" 
+0

Почему ты за 'Ā' ? Какова фактическая модель, которую вы пытаетесь сопоставить? – thefourtheye

+1

попробуйте с '\\\\' вместо '\\\' – Morb

+0

В «thefourtheye»: фактический шаблон: res = re.compile ('"([^ \ n"] | (? <= \\) ["\ n]) *" ') , чтобы соответствовать строкам типа: ms = res.match (' 'my s \ "tr"; 5;') В "Morb": '\\\\' анализируется , но не работает должным образом. – luart

ответ

1

EDIT: Окончательное регулярное выражением является адаптацией из регулярных выражений, представленных на Word Aligned

Я думаю, что вы ищете для этого регулярного выражения:

(?s)"(?:[^"\\]|\\.)*" 

См demo on regex101.

Sample Python code (проверено на TutorialsPoint):

import re 
p = re.compile(ur'(?s)"(?:[^"\\]|\\.)*"') 
ms = p.match('"my s\\"tr"; 5;') 
print ms.group(0) 
+0

Это не ответ на этот вопрос вообще! pleas get 'a' from' \ a', если вы можете – Kasramvd

+0

@Kasra: * На самом деле мне нужно сопоставить строки C++ типа «a \ "b" и * "str begin \ end" *. –

+0

@luart: Не используйте 'match', так как этот метод ищет только совпадение в начале строки. Используйте 'findall'. Или, по крайней мере, 'поиск'. –

0

Как \ является маскирующим вам нужно использовать \\ (денется один раз) в вашей строке тоже, потому что питон будет интерпретировать \a как шестнадцатеричный:

>>> '\a' 
'\x07' 

также вы должны использовать re.search потому re.match mchecks for a match only at the beginning of the string:

>>> re.search(r'(?<=\\)a','\\a') 
<_sre.SRE_Match object at 0x7fb704dd0370> 
>>> re.search(r'(?<=\\)a','\\a').group(0) 
'a' 

Но для последнего примера вам не нужно оглядываться на все, что вы можете использовать простую группировку:

>>> re.search(r'"(.*)"','"my s\"tr"; 5;').group(0) 
'"my s"tr"' 
+0

Нет, когда я разобрал: >>> ms = res.match ('' my s \ "tr"; 5; ') I' ожидая получить «мой s» «tr». – luart

+0

@luart Итак, почему вы думаете, что «мой s \ tr?» Был бы результатом? – Kasramvd

+0

К Касте мне нужно (моя задача) получить «мой s \» tr »в результате разбора« my s » \ "tr"; 5; – luart

2

Если предположить, что исходный код компилируется, это классическое решение соответствует регулярному строковый литерал в C и C++, с учетом синтаксиса продолжения строки:

(?s)"(?:[^"\\\n]|\\.)*" 

на retrospects, так как я уже предполагаю, что исходный код компилируется, нет необходимости, чтобы предотвратить паразитные новые линии, которые не являются частью синтаксиса продолжения строки в [^"\\\n], поэтому использование только [^"\\] также будет работать.

Регулярное выражение выше соответствует всем следующей Тестовым правильно:

"a \" b" 

"a \ 
b" 

"\\" 

"\\\ 
kjsh\a\b\tdfkj\"\\\\\\" 

"kjsdhfksd f\\\\" 

"kjsdhfksd f\\\"" 

Demo on regex101

старого ответ (?s)((?<!\\)".+?(?<!(?<!\\)\\)") stribizhev терпит неудачу, чтобы соответствовать действительному случаю "kjsdhfksd f\\\"", и добавляя больше смотреть-за только решить проблему для ограниченное число \.

Возможность многократного последовательного \ в строке в строковом литерале является причиной того, почему такое регулярное выражение не работает, и почему мы не должны использовать операцию разделения для tokenize CSV с указанными полями.

+0

Обратите внимание, что это решение не было протестировано с использованием строкового литерала в C++, и я считаю, что для его работы требуется модификация. – nhahtdh

+0

Благодарим вас за nhahtdh. В основном окончательное решение от stribizhev - это изысканный ваш! – luart

1

Лучший способ, вы можете избежать повторить чередование только один символ, если «раскатывать» образец подобного:

(?s)"[^"\\]*(?:\\.[^"\\]*)*" 

Обратите внимание, что вам не нужно использовать слишком назад '.

Как было предложено nhahtdh, если вы хотите, чтобы проверить/что вся строка находится на одной линии, вам нужно только, чтобы исключить \n из классов персонажей:

(?s)"[^"\\\n]*(?:\\.[^"\\\n]*)*" 
Смежные вопросы