Python re.sub 字符串上的多行
Posted
技术标签:
【中文标题】Python re.sub 字符串上的多行【英文标题】:Python re.sub multiline on string 【发布时间】:2016-02-26 16:12:43 【问题描述】:我尝试使用标志 re.MULTILINE。
我阅读了这些帖子: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。你有什么想法吗?
【问题讨论】:
你需要使用re.S
标志而不是re.M
,并将点放在字符类之外。
基本上您希望[.\n]
匹配除*/
之外的任何内容,对吗?为什么不使用[^\*\/]+
?这将使\/\*[^\*]*\*\/
匹配您的多行注释而没有标志。
【参考方案1】:
您需要将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
但是,这不是最好的解决方案,因为在大多数情况下,多行 cmets 很长。最好的是 unrolling-the-loop 技术。上面的正则表达式可以像这样“展开”:
/\*[^*]*(?:\*(?!/)[^*]*)*\*/
见regex demo
【讨论】:
感谢您的出色回应和干净的正则表达式! 仅供参考:此解决方案不支持嵌套的多行 cmets。 @alexroat 如果您需要更好的性能,请使用/\*[^*]*(?:\*(?!/)[^*]*)*\*/
以上是关于Python re.sub 字符串上的多行的主要内容,如果未能解决你的问题,请参考以下文章
为啥 re.sub() 在 Python 中默认添加不匹配的字符串?