Python使用re.finditer生成迭代对象无返回 单独正则测试正常
问题原因定位
re.VERBOSE模式的空白剔除规则:开启该模式后,正则字符串中所有未被转义的空白字符(空格、换行、制表符)都会被直接忽略,不计入实际匹配逻辑:- 左中括号的匹配片段
( \[)里,括号和左中括号之间的空格是裸写的未转义字符,会被VERBOSE模式删掉,导致正则变成直接匹配左中括号,和日志里“用户名→空格→左中括号”的实际结构错位 - 右中括号的匹配片段
(\] ")里,右中括号和双引号之间的空格是裸写的未转义字符,同样会被删掉,导致正则变成直接匹配右中括号紧跟双引号,和日志里“右中括号→空格→双引号”的实际结构错位
- 左中括号的匹配片段
- 贪婪匹配逻辑不兼容:
(?P<request>.+)采用默认贪婪规则,会从双引号后的请求位置开始一直匹配到整行末尾,不会给后续的闭合双引号"留下匹配空间,最终触发匹配失败。 - 单独测试正则时能正常运行,是因为测试时没有开启
re.VERBOSE模式,此时裸写的空格会被当做实际匹配字符生效;一旦加上VERBOSE参数,规则就发生了变化。
修正方案
- 把所有需要作为匹配规则的固定空格、双引号都做转义,避免被VERBOSE模式当格式排版内容删掉
- 将请求字段的贪婪匹配改为非贪婪匹配,确保在碰到第一个闭合双引号时就停止匹配
可正常运行的完整代码
import re # 修正后的正则 pattern = r""" (?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) (\ \-\ ) (?P<user_name>[a-z]{1,100}\d{4}|\-{1}) (\ \[)(?P<time>\d{2}\/[A-Za-z]{3}\/\d{4}\:\d{2}\:\d{2}\:\d{2}\ -\d{4}) (\]\ \") (?P<request>.+?) (\") """ # 测试文本 text = """146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622 197.109.77.178 - kertzmann3129 [21/Jun/2019:15:45:25 -0700] "DELETE /virtual/solutions/target/web+services HTTP/2.0" 203 26554 """ for item in re.finditer(pattern, text, re.VERBOSE): print(item.groupdict())
调试小技巧
在Jupyter Notebook中可以直接打印编译后的正则实际规则,排查被VERBOSE模式删掉的内容:
compiled_pattern = re.compile(pattern, re.VERBOSE) print(compiled_pattern.pattern)
打印出来的字符串就是VERBOSE模式下实际生效的匹配规则,可以直接对照日志内容找匹配错位的位置。
内容的提问来源于stack exchange,提问作者user9155539
相关产品推荐
相关产品推荐

