2015-11-24 6 views
3

Я пытаюсь использовать флаг re.MULTILINE.Python re.sub multiline on string

Я читаю эти сообщения: Bug in Python Regex? (re.sub with re.MULTILINE), Python re.sub MULTILINE caret match, но это не сработает. Код:

import re 
if __name__ == '__main__': 

    txt = "\n\ 
<?php\n\ 
/* Multi-line\n\ 
comment */\n\ 
$var = 1;\n" 
    new_txt = re.sub(r'\/\*[.\n]*?\*\/', '', txt, flags=re.MULTILINE) 
    print("\n=========== TXT ============") 
    print(txt) 
    print("\n=========== NEW TXT ============") 
    print(new_txt) 

Выходной код:

=========== TXT ============ 

<?php 
/* Multi-line 
comment */ 
$var = 1; 


=========== NEW TXT ============ 

<?php 
/* Multi-line 
comment */ 
$var = 1; 

Но new_txt не должна содержать многострочный комментарий. Я хочу получить txt без многострочного комментария. Есть ли у вас какие-либо идеи ?

+0

Вы должны использовать 're.S' флаг не' re.M' и поместите точку вне класса символов. –

+0

В основном вы хотите, чтобы '[. \ N]' соответствовало чему-либо, но '* /' правильно? Почему бы не использовать '[^ \ * \ /] +'? Это сделало бы '\/\ * [^ \ *] * \ * \ /' совпадением вашего многострочного комментария без флагов. – Noxeus

ответ

3

Вам нужно заменить re.MULTILINE с re.DOTALL/re.S и съехать период вне класса символов, как внутри него, точка соответствует символу ..

re.MULTILINE Обратите внимание, что только переопределяет поведение ^ и $, которые вынуждены соответствовать в начале/конце линии, а не всю строку. Флаг re.DOTALL переопределяет поведение . внутри шаблона вне класса символов только. Он также начинает сопоставлять символ новой строки.

Итак, регулярное выражение, которое вы можете использовать для текущего примера: /\*.*?\*/. Он соответствует буквальному /* с /\*, затем .*? соответствует как можно меньшему количеству символов, вплоть до */ (соответствует \*/).

Смотрите код демо:

txt = """\n\ 
<?php\n\ 
/* Multi-line\n\ 
comment */\n\ 
$var = 1;\n""" 
new_txt = re.sub(r'/\*.*?\*/', '', txt, flags=re.S) 
print("\n=========== TXT ============") 
print(txt) 
print("\n=========== NEW TXT ============") 
print(new_txt) 

См IDEONE demo

Однако, это не самое лучшее решение, так как в большинстве случаев многострочные комментарии очень долго. Лучшим является техника unrolling-the-loop. Регулярное выражение может быть выше «раскатали», как это:

/\*[^*]*(?:\*(?!/)[^*]*)*\*/ 

Смотрите regex demo

+0

Спасибо за отличный ответ и чистое регулярное выражение! – jedema

+1

Just FYI: Это решение не поддерживает вложенные многострочные комментарии. –