2012-02-10 3 views
1

У меня есть несколько строк, которые я бы хотел заменить, но не понимаю, почему он не работает. По какой-то причине период в строке останавливает сопоставление для регулярного выражения.Период останавливает многострочное регулярное выражение в Python?

Моя строка:

s = """ 
[some_previous_text] 
<start> 
one_period . 
<end> 
[some_text_after] 
""" 

То, что я хотел бы закончить с:

s = """ 
[some_previous_text] 
foo 
[some_text_after] 
""" 

То, что я изначально пытался, но ничего не найдено:

>>> import re 
>>> s = "<start>\none_period .\n<end>" 
>>> print re.sub("<start>[^.]*<end>", "foo", s) 
<start> 
one_period . 
<end> 

Однако, когда я взял период, он работал нормально:

>>> import re 
>>> s = "<start>\nno_period\n<end>" 
>>> print re.sub("<start>[^.]*<end>", "foo", s) 
foo 

Кроме того, когда я ставлю <end> тега до периода, она соответствует первому <end> тегу:

>>> import re 
>>> s = "<start>\n<end>\none_period .\n<end>" 
>>> print re.sub("<start>[^.]*<end>", "foo", s) 
foo 
one_period . 
<end> 

Так что же здесь происходит? Почему период останавливает совпадение [^.]*?

EDIT:

решаемые

я ошибочно думал, что каратного ^ был для согласования новой строки. Мне нужен был флаг re.DOTALL (как указано Amber). Вот выражение я теперь с помощью:

>>> import re 
>>> s = "<start>\none_period .\n<end>" 
>>> print re.sub("<start>.*<end>", "foo", s, flags=re.DOTALL) 
foo 

ответ

3

Почему бы и нет? [^.] - это «набор всех символов, который не является .» и, следовательно, не соответствует периодам.


Возможно, вы вместо того, хотел просто поставить .* (любое количество любых символов) вместо [^.]*?

Для согласования по новой строки укажите re.DOTALL:

re.sub("<start>.*<end>", "foo", s, flags=re.DOTALL) 
+0

, если я использую '. *', Однако он ничего не соответствует (т. Е. 'Re.sub (" . * "," foo ", s)'). Что было бы правильным выражением замещения? – user749618

+0

Если вы хотите, чтобы '.' соответствовал линиям, вам нужно использовать флаг' re.DOTALL'. http://docs.python.org/library/re.html#re.DOTALL – Amber

+0

're.sub (" . * "," foo ", s, flags = re.DOTALL)' работает! Большое спасибо. – user749618

1

Это потому, что [^.]* является инвертированный символьный класс, который соответствует любому символу, кроме периода.

Возможно, вы захотите что-то вроде <start>.*?<end> вместе с модификатором re.S, что делает точку совпадающей с символами новой строки.

re.sub("<start>.*?<end>", "foo", s, flags=re.S) 
+0

Так что было бы правильным выражение для использования? – user749618

+0

@ user749618 Я обновил свой ответ. 're.S' - это то же самое, что' re.DOTALL', который предложил Амбер. – stema

+0

Обратите внимание, что 're.sub()' принимает только аргумент flags в Python 2.7 или Python 3.1+, перед этим вам нужно будет скомпилировать регулярное выражение с установленным флагом или использовать что-то вроде '[\ s \ S] *? 'вместо'. *? '. –

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