首页 > 解决方案 > 正则表达式 - 否定表达式匹配

问题描述

问题介绍

所以我已经炸毁了我的大脑,试图在工作之前/之后得到负面的看法。对于最后一个示例输入,我当前的解决方案不返回匹配项(请参阅预期输出表)。title当字符串包含不在字符串末尾的年份时,我正在努力解决如何匹配字符串的一部分。需要明确的是,我只对匹配year字符串末尾的 if 感兴趣。当前正则表达式在最后一个示例中失败,因为它NOT("Q" OR "\d*")title. 但是,我只希望它匹配NOT("Q" AND "\d{1}")。非常感谢任何提示/建议。注意使用 Python 3.8。

示例输入

AXP - Earnings call Q2 2021
AXP - Conference call 2021
BAC,BAC.PE,BAC.PL,BACRP,BML.PL,BML.PJ,BML.PH,BML.PG,BAC.PB,BAC.PK,BAC.PM,BAC.PN - Earnings call Q2 2021
GM - General Motors Company (GM) Presents at Deutsche Bank AutoTech Conference
AXP - American Express Company (AXP) Management Presents at Barclays 2020 Global Financial Services Conference

period永远是形式Q[1-4]period并且year是可选的。如果它们确实发生,它们将位于字符串的末尾。symbol并且title总是被分开-并且总是发生。

预期产出

象征 标题 时期
AXP 财报电话会议 第二季度 2021
AXP 电话会议 2021
BAC 财报电话会议 第二季度 2021
通用汽车 通用汽车公司 (GM) 出席德意志银行汽车技术会议
AXP 美国运通公司 (AXP) 管理层出席巴克莱 2020 年全球金融服务会议

我试过的

r"^(?P<symbol>[^\,]{1,8})(\,[A-Z\.]+)*\s\-\s(?P<title>[^Q\d]*)\s?(?P<period>Q\d)?\s?(?P<year>19|20\d{2})$"

标签: pythonregexregex-negation

解决方案


您可以使用

^(?P<symbol>[^,]{1,8})(?:,[A-Z.]*)*\s+-\s+(?P<title>(?:(?!Q\d).)*?)\s*(?P<period>Q\d)?\s?(?P<year>(?:19|20)\d{2})?$

请参阅正则表达式演示

注意

  • [^Q\d]*是错误的,因为它匹配除和数字之外的任何零个或多个字符Q,您需要匹配任何文本到Q+ 数字,即经过(?:(?!Q\d).)*?调和的贪婪令牌
  • (?P<year>19|20\d{2})是强制性的,但它必须是可选的并且19|20不分组,因此\d{2}仅适用于20, (?P<year>19|20\d{2})=> (?P<year>(?:19|20)\d{2})?

这里还有其他一些小的改进。

详情

  • ^- 字符串的开始
  • (?P<symbol>[^,]{1,8})- 组“符号”:除逗号外的 1 到 8 个字符
  • (?:,[A-Z.]*)*- 零个或多个逗号重复,然后是零个或多个大写字母/点
  • \s+-\s+- 用一个或多个空格括起来的连字符
  • (?P<title>(?:(?!Q\d).)*?)- 组“标题”:除换行符之外的任何字符,零个或多个,但出现次数尽可能少,不以Q+digit 字符序列开头
  • \s*- 零个或多个空格
  • (?P<period>Q\d)?- 组“句号”:一个Q和一个数字
  • \s?- 一个可选的空格
  • (?P<year>(?:19|20)\d{2})?- 可选组“年”:1920后两位数
  • $- 字符串结束。

推荐阅读