首页 > 解决方案 > 正则表达式 - 如何在一组中捕获两种模式?

问题描述

我想将两种不同的模式捕获到一个捕获/匹配组中。这甚至可能吗?

第一种模式:由空格包围的两个字符字母数字([A-Z0-9]{2})

第二种模式:两个字符的字母数字前面是字母数字和一个十进制值后面跟一个空格\b[A-Z ]*\d+\.\d{2}([A-Z0-9]{2})

这两种模式一起捕获了我想要的一切,但问题是我需要它们在单个捕获组中并按照捕获的顺序(参见预期输出)。

测试字符串

ABC WS PIT342.55USD342.55END
ABC WS YMQ234.03WS TOY234.03USD468.06END
FUR BB LAB Q10.00 199.00USD209.00END
YAS DG TYY Q AWSMSN11.32 2503.08LD VET Q JKLOLE11.32 2503.08USD5028.80END
PPP VP LAP Q10.00 M342.41EE SFD Q10.00 282.24USD644.65END
YAS DL X/XXX MO X/POP DF PSC241.30ET X/SAE DL X/KOO DL CSG269.80USD511.10END

正则表达式101

预期产出

+------------------------------------------------------------------------------+------------------------+
| ABC WS PIT342.55USD342.55END                                                 | WS                     |
| ABC WS YMQ234.03WS TOY234.03USD468.06END                                     | WS, WS                 |
| FUR BB LAB Q10.00 199.00USD209.00END                                         | BB                     |
| YAS DG TYY Q AWSMSN11.32 2503.08LD VET Q JKLOLE11.32 2503.08USD5028.80END    | DG, LD                 |
| PPP VP LAP Q10.00 M342.41EE SFD Q10.00 282.24USD644.65END                    | VP, EE                 |
| YAS DL X/XXX MO X/POP DF PSC241.30ET X/SAE DL X/KOO DL CSG269.80USD511.10END | DL, MO, DF, ET, DL, DL |
+------------------------------------------------------------------------------+------------------------+

标签: pythonregex

解决方案


例如,您可以从字符类中省略空格,因为它与本部分[A-Z ]*中的第一个不匹配。WSWS YMQ234.03WS

由于这两种模式在以 2 个字母数字和空格结尾时具有相同的部分,因此您可以使用交替 |来匹配前面的空格或第二个模式的第一部分。

(?:\b[A-Z]*\d+\.\d{2}| )([A-Z0-9]{2}) 

解释

  • (?:轮换的非捕获组|
    • \b[A-Z]*\d+\.\d{2}字边界,匹配 0+ 次字符 AZ、1+ 位、点和 2 位
    • | 匹配一个空格
  • )关闭非捕获组
  • ([A-Z0-9]{2})捕获组 1,匹配 2 次字母数字

正则表达式演示| Python 演示

示例代码

import re

strings = [
    "ABC WS PIT342.55USD342.55END",
    "ABC WS YMQ234.03WS TOY234.03USD468.06END",
    "FUR BB LAB Q10.00 199.00USD209.00END",
    "YAS DG TYY Q AWSMSN11.32 2503.08LD VET Q JKLOLE11.32 2503.08USD5028.80END",
    "PPP VP LAP Q10.00 M342.41EE SFD Q10.00 282.24USD644.65END",
    "YAS DL X/XXX MO X/POP DF PSC241.30ET X/SAE DL X/KOO DL CSG269.80USD511.10END"
]

for s in strings: 
    print(re.findall(r"(?:\b[A-Z]*\d+\.\d{2}| )([A-Z0-9]{2}) ", s))

输出

['WS']
['WS', 'WS']
['BB']
['DG', 'LD']
['VP', 'EE']
['DL', 'MO', 'DF', 'ET', 'DL', 'DL']

推荐阅读