我有一个正则表达式:
(.*\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 模块)。
Python 实现 inline (embedded) modifiers ,例如 (?s)
、(?i)
或 (?aiLmsux)
,但不作为非- 像您尝试使用的那样捕获组修饰符。
(?smi:subpattern)
适用于 Perl 和 PCRE,但不适用于 Python。
此外,在模式中的任何位置使用内联修饰符适用于整个匹配并且无法关闭。
From regular-expressions.info:
In Python, putting a modifier in the middle of the regex affects the
whole regex. So in Python, (?i)caseless
and caseless(?i)
are both case
insensitive.
示例:
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)
(又名 singleline 或 re.DOTALL
)生成 .
也匹配换行符。由于您试图将其设置为模式的一部分,因此有两种选择:
- 匹配除换行符以外的任何内容:
为整个模式设置 (?s)
(作为标志或内联传递),并使用 [^\n]*
而不是点,匹配除换行符以外的任何字符。
- 匹配所有内容,包括换行符:
使用 [\S\s]*
代替点,以匹配任何字符,包括换行符。字符类包括所有空格和所有非空格(因此,所有字符)。
对于您提供的具体案例,您可以使用以下表达式:
(?m)^DOCUMENTATION.*(\"{3}|'{3})\n-*\n?([\s\S]+?)^\1[\s\S]*
regex101 Demo
注意:这篇文章涵盖了 re module 中的内联修饰符, 而 Matthew Barnett's regex module实际上确实实现了内联修饰符(作用域标志),其行为与在 PCRE 和 Perl 中观察到的相同。