[英]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))?)
如果满足以下条件,它将匹配:
[^.?!\\n]
应该阻止它,但是像Mr.,decimals等之类的字词会干扰匹配),您可以将其替换为.+?
( DEMO )但是它可以在句子之间匹配 其他类似的解决方案是:
(?=((?<!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})
也许,以下选项之一对减少误报很有用:
nodule
”和数字之间没有句号,则不匹配。 关于这个问题,我最终使用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.