我有这个正则表达式:
cont_we_re = r"((?!\S+\s?(?:(cbf|cd3|cbm|m3|m[\\\>\?et]?|f3|ft3)))(?:([0-9,\.]+){2,})(?:\s*(?:(lb|kg)\.?s?))?)"
现在,如果后跟 kgs
或 lbs
,则后面的逻辑可选地与任何数字 block 匹配,但如果 cbf
,则不匹配>, cd3
, cbm
, m3
等在数字 block 之后。它非常适合这些示例案例:
s1 = "18300 kg 40344.6 lbs 25000 m3"
s2 = "18300kg 40344.6lbs 25000m3"
s3 = "18300 kg KO"
s4 = "40344.6 lb5 "
s5 = "40344.6 "
我正在使用带有 re.IGNORECASE
标志的 re.finditer()
,像这样:
for s in [s1, s2, s3, s4, s5]:
all_val = [i.group().strip() for i in re.finditer(cont_we_re, s, re.IGNORECASE)]
给我这个输出:
['18300 kg', '40344.6 lbs']
['18300kg', '40344.6lbs']
['18300 kg']
['40344.6 lb']
['40344.6']
现在我正在尝试实现另一个逻辑:如果我们找到后跟 lbs
的数字 block ,则将其与第一优先级匹配并仅返回该匹配项,但如果找不到 lbs
并只找到数字 block 或数字 block 后跟 kgs
然后取那些。
我在不更改正则表达式的情况下完成了此操作,如下所示:
for s in [s1, s2, s3, s4, s5]:
all_val = [i.group().strip() for i in re.finditer(cont_we_re, s, re.IGNORECASE)]
kg_val = [i for i in all_val if re.findall(r"kg\.?s?", i)]
lb_val = [i for i in all_val if re.findall(r"lb\.?s?", i)]
final_val = lb_val if lb_val else (kg_val if kg_val else list(set(all_val) - (set(kg_val+lb_val))))
这给了我想要的输出(这是完美的):
['40344.6 lbs']
['40344.6lbs']
['18300 kg']
['40344.6 lb']
['40344.6']
问题是我如何在正则表达式中应用相同的逻辑,而不通过 cont_we_re
在每个匹配组上分别找到 kgs
和 lbs
对于每个字符串。我尝试了此 question 中描述的“IF-THEN-ELSE”类型正则表达式但它不能作为正则表达式的第一部分 (?
据说会在 python 中产生模式错误。有没有办法只用 cont_we_re
正则表达式来做到这一点?
最佳答案
使用 PyPi module 的可能解决方案可能正在利用 (*SKIP)(*FAIL)和环顾四周以检查是否存在 lb
(?:\d+(?:\.\d+)? ?lbs?|(?<!lb.*)(?!.*lb)\d+(?:\.\d+)?(?: kg)?|\d+(?:\.\d+)? ?kg(*SKIP)(*FAIL))
-
(?:
非捕获组-
\d+(?:\.\d+)? ?lbs?
将数字格式与可选的小数部分匹配,后跟 lb 和可选的 s -
|
或者 -
(?<!lb.*)(?!.*lb)\d+(?:\.\d+)?(?: kg)?
断言字符串不包含lb
, 然后将数字格式与可选的小数部分匹配,后跟kg
-
|
或者 -
\d+(?:\.\d+)? ?kg(*SKIP)(*FAIL)
匹配数字格式后接kg
并跳过那场比赛
-
-
)
关闭非捕获组
例如
import regex
s1 = "18300 kg 40344.6 lbs 25000 m3"
s2 = "18300kg 40344.6lbs 25000m3"
s3 = "18300 kg KO"
s4 = "40344.6 lb5 "
s5 = "40344.6 "
cont_we_re = r"(?:\d+(?:\.\d+)? ?lbs?|(?<!lb.*)(?!.*lb)\d+(?:\.\d+)?(?: kg)?|\d+(?:\.\d+)? ?kg(*SKIP)(*FAIL))"
for s in [s1, s2, s3, s4, s5]:
all_val = [i.group().strip() for i in regex.finditer(cont_we_re, s, regex.IGNORECASE)]
print(all_val)
输出
['40344.6 lbs']
['40344.6lbs']
['18300 kg']
['40344.6 lb']
['40344.6']
关于具有多层条件的Python正则表达式匹配组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59247464/