如何在python中使用内联正则表达式修饰符

时间:2015-02-05 21:00:08

标签: python regex

我有正则表达式:

(.*\n)+DOCUMENTATION.*(\"\"\"|''')\n-*\n?((.*\n)+?)(\2)(?s:.*)

女巫我正在尝试处理这样的文件:

#!/usr/bin/python
# -*- coding: utf-8 -*-

# <GNU license here>

DOCUMENTATION = """
module: foo
short_description: baz
<some more here>    
"""

<rest of the python code>

我需要从中获取DOCUMENTATION部分。

它工作得很好但不是python。问题在于内联修饰符?s:.*,我用它来捕获文件的其余部分(任何字符包括新行零次或多次)。看起来它在python中有些不同。

这里以regex101为例。当我将它切换到python时显示错误。

注意:我无法全局设置修改器。 (我只能将正则表达式规则传递给某个python模块)。

1 个答案:

答案 0 :(得分:12)

re module

中的内联修饰符

Python实现 inline (embedded) modifiers ,例如(?s)(?i)(?aiLmsux),但不是非捕获组修饰符的一部分你试图使用。
(?smi:subpattern)适用于Perl和PCRE,但不适用于Python。

此外,在模式中的任何位置使用内联修饰符都适用于整个匹配,并且无法将其关闭。

  

<强> From regular-expressions.info
  在Python中,将修饰符放在正则表达式的中间会影响   整个正则表达式。所以在Python中, (?i)caseless caseless(?i) 都属于这种情况   不敏感的。

示例:

import re

text = "A\nB"
print("Text: '%s'\n---" % text)
patterns = [ "a", "a(?i)", "A.*B", "A(?s).*B", "A.*(?s)B"]

for p in patterns:
    match = re.search( p, text)
    print("Pattern: '%s'    \tMatch: %s" % (p, match.span() if match else None))

<强>输出:

Text: 'A
B'
---
Pattern: 'a'            Match: None
Pattern: 'a(?i)'        Match: (0, 1)
Pattern: 'A.*B'         Match: None
Pattern: 'A(?s).*B'     Match: (0, 3)
Pattern: 'A.*(?s)B'     Match: (0, 3)

ideone Demo

解决方案

(?s)(又名单行re.DOTALL)使 . 也匹配换行符。而且由于您尝试将其设置为模式的一部分,因此有两种选择:

  1. 匹配除换行符之外的任何内容
    为整个模式设置(?s)(以标记或内联方式传递),并使用 [^\n]* 代替点,以匹配除换行之外的任何字符。
  2. 匹配包括换行符在内的所有内容
    使用 [\S\s]* 代替点,以匹配包括换行符在内的任何字符。字符类包括所有空格和所有不是空格(因此,所有字符)。

  3. 对于您提供的特定情况,您可以使用以下表达式:

    (?m)^DOCUMENTATION.*(\"{3}|'{3})\n-*\n?([\s\S]+?)^\1[\s\S]*
    

    regex101 Demo

    注意:这篇文章介绍re module中的内联修饰符,而Matthew Barnett's regex module实际上实现了内联修饰符(作用域标记),其行为与PCRE和Perl。