如何解决正则表达式代码太长且效率低下我想让它变得更好
编辑:好的,我很抱歉,因为我对问题的第一个措辞过于简单,技术上正确的答案不适用于我的案例,所以这次我会尽量详细。
我正在构建一个正则表达式来捕获单个或复合代码。 每个代码都以“H”、“G”、“EUH”或“AUG”开头,后跟三位数字 (H123) 或三位数字、一个点和一位数字。 (H123.1)。 第一位不能是零。
每个 H 代码后可以跟一个或多个以下字符:“idDfF”.(H231Df)。 每个 P 代码后面可以跟一个或多个这些字符:“AEBDab”。(P333a)。 每个 EUH 代码后面都可以跟“A”。(EUH123A)。
化合物示例:H123Df+H234+H234.1+H342.1Fd 和 P123.1+P555D 空格可以在字符串中的任何地方,除了 3 位数字,这些数字总是相互跟随,没有空格。 点或破折号可以在末尾的额外字符之前(H123-Df,H123.Df)
我需要匹配每个复合或单个代码。请注意,在我之前的尝试中,我检测到 H567+H890+H654 正确,但也检测到 H567、H890 和 H654,这是错误的。一旦匹配了一个集合,它的内部代码不应再被视为单个代码。
我目前的方法实际上是 4 种不同的正则表达式代码,每组代码一个。它主要有效(我猜),但它非常乏味,如果将另一个代码添加到化合物中将无法工作,并且在正则表达式中添加更复杂的东西时,它非常难以维护。 这是 P 代码的正则表达式示例。
`p = "P\s*\d{3}[.\s-]*[AEBDab]*\s*[+/]\s*P*\s*\d{3}[.\s-]*[AEBDab]*\s*[+/]\s*P*\s*\d{3}[.\s-]*[AEBDab]*|P\s*\d{3}[.\s-]*[AEBDab]*\s*[+/]\s*P*\s*\d{3}[.\s-][AEBDab]*|P\s*\d{3}[.\s-]*[AEBDab]*\s`"
如您所见,它非常长且效率低下,编辑一个小东西会花费很多时间并且很容易出错。
我怎样才能以更好的方式实现这一目标?是制作 4 个正则表达式更好还是仅使用一个来捕获所有 4 个代码的所有格式?
编辑: 一个真实的版本看起来就像这样:
text = "random text
H326random text H243Df+H546+H677-Drandom text
randomtext P234a+P333.Ddrandom text
someother randomtexts"
output = [H326,H243+H546+H677,H234+H333]
注意:所提供的文本中的空格非常随机,因为它们是用 pdfminer 库解析的 PDF 文本,它非常混乱的顺序和空格,但它是我发现的唯一一个实际上可以“读取”所有 10k 的库我有 PDF 文件,其他库会产生空字符串,或者只是读取 PDF 的一部分。
注意:如果你能解释一下你的答案,因为我在工作时总是在发现新的格式,我希望能够根据需要编辑正则表达式。
谢谢!
解决方法
这样的事情可能对你有用:
import re
i = 'random text H326 H243+H546+H677 H234+H333 some other random texts X567+X890+X654'
capture_letters = 'HPGX'
regex = rf'[{capture_letters}]\d(?:\+[{capture_letters}]\dgithub-comment)*'
print([i.group(0) for i in re.finditer(regex,i)])
将任何有效的字母作为 capture_letters
字符串中的代码开头。
如果有大写字母,您也可以使用 A-Z
。
根据您展示的样品,您可以尝试以下操作吗?
import re
value = 'X123 X234+X567 some intermixed text X567+X890+X654 some extra text'
regex = r'(([a-zA-Z]+\d{3}\+?){1,})'
print([key.group(0) for key in re.finditer(regex,value)])
输出如下:
['X123','X234+X567','X567+X890+X654']
,
因此,根据您的评论,您似乎可以将 re.findall
与以下模式一起使用:
\b[HPGX]\d{3}(?:\+[HPGX]\d{3})*\b
查看在线demo
-
\b
- 词边界。 -
[HPGX]
- 提到的字符类中的单个字符。 -
\d{3}
- 三位数。 -
(?:
- 打开非捕获组:-
\+
- 文字“+”。 -
[HPGX]
- 提到的字符类中的单个字符。 -
\d{3}
- 三位数。 -
)*
- 关闭非捕获组并匹配 0 次以上(贪婪)。
-
-
\b
- 词边界。
import re
txt = 'random text H326 H243+H546+H677 H234+H333 some other random texts'
lst = re.findall(r'\b[HPGX]\d{3}(?:\+[HPGX]\d{3})*\b',txt)
print(lst)
打印:
['H326','H243+H546+H677','H234+H333']
,
您可以使用 recursive regex
简化带有 regex
的正则表达式
(不是 re
)模块。
import regex
text = """random text
H326random text H243Df+H546+H677-Drandom text
randomtext P234a+P333.Ddrandom text
someother randomtexts"""
m = regex.finditer(r'(H\s*\d{3}[.\s-]*[idDfF]*|(?:AU)?G\s*\d{3}(?:\.\d)|P\s*\d{3}[.\s-]*[AEBDab]*|EUH\s*\d{3}\s*A?)(?:\+(?1))*',text)
print([i.group(0) for i in m])
结果:
['H326','H243Df+H546+H677-D','P234a+P333.D']
说明:
- 正则表达式
(H\s*\d{3}[.\s-]*[idDfF]*|(?:AU)?G\s*\d{3}(?:\.\d)|P\s*\d{3}[.\s-]*[AEBDab]*|EUH\s*\d{3}\s*A?)
是代码的规范。如果我不是 完全理解规则后,您将很容易修复正则表达式。 该模式用括号括起来,并在以下模式中作为(?1)
重新使用。 - 正则表达式
(?:\+(?1))*
是一个加号和(?1)
的簇, 上面定义的递归正则表达式。 - 匹配的子字符串被称为
group(0)
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。