用Python正则表达式匹配多行make变量赋值
我正在尝试从一个多行的变量赋值中提取出多行的值。下面这个测试案例在输入字符串中找不到匹配的内容,我必须承认我搞不清楚为什么会这样。如果能帮我让这个示例代码在标准输出上打印出 "a \ b",我将非常感激。
#!/usr/bin/env python
def test():
s = r"""
FOO=a \
b
"""
import re
print type(s),s
regex = re.compile(r'^FOO=(.+)(?<!\\)$', re.M)
m = regex.search(s)
print m.group(1)
if __name__ == '__main__':
test()
4 个回答
你的示例文本中有很多空格,包括反斜杠后面。我想这不是你想要的,因为反斜杠的作用是用来转义换行符,换行符通常表示输入的结束。
不过,反斜杠也可以用来转义其他字符,包括反斜杠本身。如果一个值恰好以反斜杠结尾,在makefile中会显示为两个反斜杠。你的正则表达式中的“向后查找”会“看到”第二个反斜杠,并错误地将其视为行的继续。
如果你想添加另一个向后查找来检查反斜杠是否被转义,我建议你别这样做。这种方法已经讨论过很多次,向后查找的方式无法奏效。你需要的是像这样的东西:
regex = re.compile(r'^FOO=([^\n\\]*(?:\\.[^\n\\]*)*)$', re.M | re.S)
第一个 [^\n\\]*
会尽可能多地匹配非换行和非反斜杠的字符,然后将控制权交给下一部分。如果字符串的末尾还没到,它会尝试匹配一个反斜杠后面跟着任意字符(包括换行符,因为有 re.S
修饰符),然后再跟一些“正常”的字符。它会这样循环下去,直到(假设输入是有效的)遇到一个未转义的换行符或输入的末尾。
虽然是 re.S
修饰符让点号可以匹配换行符,但 re.M
修饰符也是必要的;它让 ^
匹配行的开头,$
匹配行的结尾,正如 @stema 所解释的那样。
你的问题是,默认情况下,.
这个符号是无法匹配换行符的。如果你开启“Dotall”模式,它就可以工作了。
regex = re.compile(r'^FOO=(.+)(?<!\\)$', re.M | re.S)
你可以通过使用re.S
来实现这个功能。
这样输出的结果将会是
a \
b
你的模式确实可以匹配包含换行符的内容。
我不太确定你想用多行模式re.M
达到什么效果。这个模式会让^
和$
分别匹配行的开始和结束。我想你可以把它去掉。
我也不太明白你想用负向前瞻(?<!\\)
实现什么,建议你明确一下你期望的输出结果。(你是想去掉“\”和换行符之间的内容吗?)
re.M代表的是re.MULTILINE,这个选项和点号(.)的含义没有关系,它主要影响的是开头(^)和结尾($)的符号。
如果你想让点号(.)也能匹配换行符(\n),你需要使用re.DOTALL这个选项。
def test():
s = r"""
FOO=a \
b
"""
import re
print repr(s)
print '---------------------'
regex = re.compile(r'^FOO=(.+)(?<!\\)$', re.M)
print regex.search(s).group(1)
print '---------------------'
regex = re.compile(r'^FOO=(.+)(?<!\\)$', re.M|re.DOTALL)
print regex.search(s).group(1)
test()
结果
' \n\nFOO=a \\ \n\n b\n\n '
---------------------
a \
-----
'a \\ '
---------------------
a \
b
-----
'a \\ \n\n b\n\n '