【问题标题】:Python re.sub multiline on stringPython re.sub 字符串上的多行
【发布时间】: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] 匹配除*/ 之外的任何内容,对吗?为什么不使用[^\*\/]+?这将使\/\*[^\*]*\*\/ 匹配您的多行注释而没有标志。

标签: python regex replace


【解决方案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 如果您需要更好的性能,请使用/\*[^*]*(?:\*(?!/)[^*]*)*\*/
猜你喜欢
  • 1970-01-01
  • 2014-10-12
  • 1970-01-01
  • 1970-01-01
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
  • 1970-01-01
相关资源
最近更新 更多