python regex在搜索字符串后的某个点查找特定长度的数字

kkbh8khc  于 2023-06-07  发布在  Python
关注(0)|答案(2)|浏览(166)

编辑:我可能已经解决了我的问题,使用一个消极的向后看,但我担心我只是偶然发现了一个特殊的情况下,这一工作,或b)有它~正确,但非常stilted/低效。非常感谢任何反馈,我真的很想知道为什么原来的模式不起作用。下面是现在似乎正在工作的正则表达式模式:
qtD = re.compile('qt[^cy].*?(?<!\<|\>|\d)(\d{3})(?:\D|$)', re.I)
以下是原始消息:
我试图在Python(3.2)中使用标准正则表达式包re来完成以下操作。这看起来不应该很复杂,但我不知道出了什么问题。
下面是一个示例字符串:s = 'EKG done this AM with QT 560 and QTC wnl at 535ms, higher than on exam performed 5/3/2015 which showed...
在本例中,我试图通过re.findall()返回的只是数字'560'-也就是说,在'QT'之后的某个时刻出现的第一个数字,并且是一个3位整数。
下面是我目前使用的正则表达式模式:
qtD = re.compile('qt[^cy].*?[^\<\>\d](\d{3})(?:\D|$)', re.I)
所以,基本上:

  • 查找QT(但不是QTC或QTY)
  • 。。。后面可能跟任意数量的字符
  • ...并返回找到的前3位整数(\d {3})
  • ...但仅当该3位整数前面不紧接“<”、“>”或其他数字时
  • ...并且紧跟行尾$或非数字\D

我是这样搜索的:re.findall(qtD, s)
上面的工作很好,但只有在'QT'和数字之间有一个长度至少为2的字符串(字符或空格)的情况下。换句话说,“QT560”返回560。“QT间期在560处正常”返回560。“QT:560”返回560。
但是,如果字符串如上所示,“... QT 560...”,那么正则表达式将继续读取并返回下一个3位数,535。
我尝试过其他的方法,比如让[^\<\>\d]变懒,比如[^\<\>\d]?,或者重复0或1次[^\<\>\d]{0,1},但是如果它没有找到任何3位数之前的数字,比如560和535,那么它就会开始做一些事情,比如返回2015年5月3日的“015”,在这种情况下,我希望返回一个空列表。
谢谢你的帮助。

r1zk6ea1

r1zk6ea11#

在您的模式中,您至少匹配2个字符[^cy][^\<\>\d]
相反,你可以使用2个lookaroundAssert:

\bqt(?![cy]).*?(?<![\d<>])(\d{3})(?:\D|$)

模式匹配:

  • \bqt防止部分字匹配的字边界,然后匹配qt
  • (?![cy])负向前看,不直接向右侧Assertcy
  • .*?匹配任何字符,尽可能少
  • (?<![\d<>])负向后查找,不向左Assert数字或<>
  • (\d{3})捕获组1中的3位数字(由re.findall返回)
  • (?:\D|$)匹配非数字或Assert字符串的结尾

Regex demo
这也将匹配QT560中的560
后面可能跟有任意数量的字符
或者先匹配3个数字,然后是lookbehindAssert:

\bqt(?![cy]).*?(\d{3})(?<![\d<>]\d{3})(?:\D|$)

Regex demo

iszxjhcz

iszxjhcz2#

一般来说,问题就出在这一节

[^cy]    # requires 1 character
.*? 
[^<>\d]  # requires 1 character

qt\d[3]之间至少需要2个字符
而这个

[^cy]        # requires 1 character
.*?
(?<![<>\d])  # requires 0 character

qt\d[3]之间至少需要1个字符
由于QT 560之间只有一个字符,因此此正则表达式
qt[^cy].*?[^<>\d](\d{3})(?:\D|$)将仅与QT 560 and QTC wnl at 535m匹配
在示例字符串中,其中535在捕获组1中。
如果在QT 560之间添加另一个空格,则可以看到此结果
https://regex101.com/r/yMMjtD/1
这可能更好地解决问题,或类似
qt(?![cy]).+?(?<![<>\d])(\d{3})(?:\D|$)
https://regex101.com/r/JjB7kL/1

相关问题