python - (Python)如何根据几个正则表达式检查一个长字符串?
问题描述
我想确保一个长字符串可以一次匹配多个正则表达式。
我有一个长的多行字符串,其中包含文件列表和文件的一些内容。
DIR1\FILE1.EXT1 CONTENT11
DIR1\FILE1.EXT1 CONTENT12
DIR1\FILE1.EXT1 CONTENT13
DIR1\FILE2.EXT1 CONTENT21
DIR2\FILE3.EXT2 CONTENT31
DIR3\FILE3.EXT2 CONTENT11
该列表通常包含数十万行,有时甚至数百万行。
我想检查列表是否包含预定义的情侣文件/内容:
FILE1 CONTENT11
FILE1 CONTENT12
FILE3 CONTENT11
我知道我可以通过将字符串与一些正则表达式进行匹配来检查字符串是否包含所有这些对
"^\S*FILE1\S*\tCONTENT11$"
"^\S*FILE1\S*\tCONTENT12$"
"^\S*FILE3\S*\tCONTENT11$"
import re
def all_matching(str, rxs):
res = True
for rx in rxs:
p = re.compile(rx, re.M)
res = res and p.search(str)
return(res)
input1 = """DIR1\\FILE1.EXT1\tCONTENT11
DIR1\\FILE1.EXT1\tCONTENT12
DIR1\\FILE1.EXT1\tCONTENT13
DIR1\\FILE2.EXT1\tCONTENT21
DIR2\\FILE3.EXT2\tCONTENT31
DIR3\\FILE3.EXT2\tCONTENT11"""
input2 = """DIR1\\FILE1.EXT1\tCONTENT11
DIR1\\FILE1.EXT1\tCONTENT12
DIR1\\FILE1.EXT1\tCONTENT13
DIR1\\FILE2.EXT1\tCONTENT21
DIR2\\FILE3.EXT2\tCONTENT31"""
rxs = [r"^\S*FILE1\S*\tCONTENT11$",r"^\S*FILE1\S*\tCONTENT12$",r"^\S*FILE3\S*\tCONTENT11$"]
if all_matching(input1,rxs):
print("input1 matches all rxs") # excpected
else:
print("input1 do not match all rxs")
if all_matching(input2,rxs):
print("input2 matches all rxs")
else:
print("input2 do not match all rxs") # expected because input2 doesn't match wirh rxs[2]
但是,由于在我的情况下输入字符串很长,我宁愿避免多次启动搜索......
我觉得应该可以以这种方式更改 all_matching 函数。
任何帮助都感激不尽!
编辑
通过提供的示例代码阐明了问题
解决方案
您可以从您拥有的正则表达式字符串构建单个正则表达式,这将要求所有正则表达式在输入字符串中找到匹配项。
生成的正则表达式看起来像
\A(?=(?:.*\n)*?\S*FILE1\S*\tCONTENT11$)(?=(?:.*\n)*?\S*FILE1\S*\tCONTENT12$)(?=(?:.*\n)*?\S*FILE3\S*\tCONTENT11$)
请参阅正则表达式演示。
基本上,它将匹配:
(?m)
- 一个re.M
/re.MULTILINE
嵌入标志选项\A
- 字符串开头(不是行首!),下面所有的lookaheads都会被一个一个触发,从头开始检查字符串,直到其中一个失败(?=(?:.*\n)*?\S*FILE1\S*\tCONTENT11$)
- 一个积极的前瞻,即在当前位置的右侧,需要存在(?:.*\n)*?
- 0 或更多(但尽可能少,只有在后续子模式不匹配时才会尝试该模式)\S*
- 0+ 个非空格FILE1
- 一个字符串\S*
- 0+ 个非空格\tCONTENT11
- 制表符和CONTENT11
子字符串$
- 行尾(因为(?m)
允许$
匹配行尾)
(?=(?:.*\n)*?\S*FILE1\S*\tCONTENT12$)
- 与前一个类似的前瞻工作,需要FILE1
和CONTENT12
子字符串在线(?=(?:.*\n)*?\S*FILE3\S*\tCONTENT11$)
- 与前一个类似的前瞻工作,需要FILE3
和CONTENT11
子字符串。
在 Python 中,它看起来像
rxs = [r"^\S*FILE1\S*\tCONTENT11$",r"^\S*FILE1\S*\tCONTENT12$",r"^\S*FILE3\S*\tCONTENT11$"]
pat = re.compile( r"(?m)\A(?=(?:.*\n)*?{})".format(r")(?=(?:.*\n)*?".join([rx[1:] for rx in rxs])) )
然后,检查方法将如下所示
def all_matching(s, pat):
return pat.search(s)
在线查看完整的 Python 演示。
推荐阅读
- vba - 化学式中的下标数字来自选择
- groovy - 通过 groovy 脚本进行 ODI 选择性逆向工程
- flutter - 在 Flutter 中悬停在 Dragtarget 上时可拖动触发错误信息
- angular - 使用角度将数据导出到excel模板
- apache-spark - 在 Spark SQL 查询中计算派生表的大小
- amazon-web-services - 在 YAML cloudformation 中加入多个资源
- javascript - 搜索时下拉列表向上移动
- html - 如何将自定义颜色应用于嵌入在 Boostratp 3.3.x 样式的链接中的 glyficon 图标?
- android-studio - IntelliJ:在伴随对象和最后一个光标位置之间跳转
- c# - 关键字不支持“数据源”错误