繁体   English   中英

Python正则表达式负向后看

[英]Python Regex Negative Lookbehind

我有一个大型的CT扫描结果和印象数据库。 我正在尝试构建一个正则表达式,该表达式搜索整数或浮点数,后跟与单词“ nodule”相邻的“ mm”。 到目前为止,这是我的正则表达式:

nodule_4mm_size = "(?s).*?([0-4]*\.*[0-9]+\s*[mM]{2})[\w\W]{0,24}[Nn]odule|(?s)[Nn]odule[\w\W]{0,24}.*?([0-4]*\.*[0-9]+\s*[mM]{2})”

但是,我需要确保在这些发现之前没有进行之前或之前的测量。 放射科医生指的是以前的扫描。 因此,我尝试在后面进行负向查找,如下所示:

(?<!previously measured)\?[Nn]odule[\w\W]{0,24}[^\.\d]([0-4]\s*[mM]{2}|[0-3]\.[0-9]\s*[mM]{2}|4\.0+\s*[mM]{2})

但是,我无法使其正常工作。 以下面的段落为例。

“例如,最大的结节位于右下叶,目前尺寸为4.4毫米(图像#82,系列3),先前在2011年9月1日测量为3.6毫米。”

在这种情况下,我希望将正则表达式打到4.4毫米而不是3.6毫米。 此外,如果找到多个匹配,我只想保留找到的最大匹配。 例如,

“例如,最大的结节位于右下叶,目前测量为4.4毫米(图像#82,系列3),先前在2011年9月1日测量为3.6毫米。发现另一个结节为2.2毫米。

在这种情况下,我要确保仅识别4.4毫米。

任何帮助将不胜感激。 只是无法让这种消极的后盾起作用! 谢谢!

两种可能性:

1)使用lookbehinds:

(?<!previously measured )(?<![0-9.])([0-9]+(?:\.[0-9]+)?) ?mm

第一个检查"previously measured "是否不在数字之前,第二个检查是否在数字之前没有数字或点(否则,点后的4个将匹配。请记住,正则表达式引擎将返回第一个结果)左边)。

2)使用捕获组:

previously measured [0-9]+(?:\.[0-9]+)? ?mm|([0-9]+(?:\.[0-9]+)?) ?mm

想法是匹配您想要避免的事。 当捕获组1存在时,您将获得结果。

关于最大数量,请使用re.findall方法并获得最大的结果(正则表达式无法解决此类问题)。

如果附近需要nodule词,可以尝试:

(?:((?<!previously measured\s)\d+.\d+\s*mm)(?:[^.?!\n]*?)?nodule|nodule(?:[^.?!\n]*?((?<!previously measured\s)\d+.\d+\s*mm))?)

演示

如果满足以下条件,它将匹配:

  • 结节与以mm为单位的值在同一句子中( [^.?!\\n]应该阻止它,但是像Mr.,decimals等之类的字词会干扰匹配),您可以将其替换为.+? DEMO )但是它可以在句子之间匹配
  • 该值在字根结节之前或之后(在此oreder中,如果之前有值,将首先匹配),
  • 值将以组的形式捕获:--1之前,-2之后,
  • 它应该与g和i模式一起使用

其他类似的解决方案是:

(?=((?<!previously measured\s)\d+.\d+ mm)[^.?!]+nodule)|(?=nodule[^.?!]+((?<!previously measured\s)\d+\.\d+ mm))

演示

仅基于环视,它不会直接匹配文本,而是零长度位置,并且会将值捕获到组中。

让我们分解一下,保留相关部分。 到目前为止,您有2个选择:

选项1 (数字后跟“ nodule ”):

([0-4]\.\d+\s*[mM]{2})[\s\S]{0,24}[Nn]odule

选项2 (“ nodule ”后跟数字):

[Nn]odule[\s\S]{0,24}([0-4]\.\d+\s*[mM]{2})

您应该知道正则表达式引擎是贪婪的 这意味着[\\s\\S]{1,24}将尝试尽可能匹配,匹配不一定最接近“ nodule ”的数字。 例如,

Pattern: [Nn]odule[\s\S]{0,24}([0-4]\.\d+\s*[mM]{2})

Text: ... nodule measured 1.4 mm. Another 3.2 mm ...
                                          ^    ^
                                          |    |
          matches this second occurence.  +----+

要解决此问题,请添加一个额外的? 经过量词使懒惰 因此,不是使用[\\s\\S]{0,24} ,而是使用[\\s\\S]{0,24}?


例如,最大的结节位于右下叶,目前尺寸为4.4毫米

此示例的“ nodule ”间隔超过24个字符。 您应该增加中间的字符数。 也许[\\s\\S]{0,70}?


所以我正在尝试负面的回望

Lookbehinds仅声明某个位置之前的文本。 为避免这种情况,我建议匹配文本“ previously measured ”,并在文本周围使用一些字符。 那么,您怎么知道不考虑这些情况? 容易,不要创建捕获。 因此,您将匹配类似

[\s\S]{0,10}previously measured[\s\S]{0,10}

并取消匹配,因为它没有返回任何组。 此外,您可以在此处包括不同的例外:

[\s\S]{0,10}(?:previously measured|previous scan|another patient|incorrectly measured)[\s\S]{0,10}

如果找到多个匹配,我只想保留找到的最大匹配

使用regex不能做到这一点。 循环输入代码以查找最大的代码。


结果:

在这些条件下,我们有:

[\s\S]{0,10}previously measured[\s\S]{0,10}|([0-4]\.\d+\s*[mM]{2})[\s\S]{0,70}?[Nn]odule|[Nn]odule[\s\S]{0,70}?([0-4]\.\d+\s*[mM]{2})

演示


额外条件要检查

也许,以下选项之一对减少误报很有用:

  1. 不允许在换行符之后进行匹配。
  2. 如果“ nodule ”和数字之间没有句号,则不匹配。
  3. 在小节附近寻找日期。

关于这个问题,我最终使用nltk模块将报告标记为单个句子。 适用于所有实例的最终正则表达式为:

nodule_search = "[\s\S]{0,10}(?:previously measured|compared to )[\s\S]{0,10}|(\d[\.,]\d+|\d+|\d\d[\.,]\d+)\s*[mM]{2}[\s\S]{0,40}?[Nn]odule|[Nn]odule[\s\S]{0,40}?(\d[\.,]\d+|\d+|\d\d[\.,]\d+)\s*[mM]{2}"

因此,在这种情况下,我没有在后面进行否定的查找,而是做了一个捕获组。

谢谢各位的意见。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM