1

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

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 毫米。

任何帮助将不胜感激。只是无法让这种负面的后视效果发挥作用!谢谢!

4

4 回答 4

1

两种可能:

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方法并在之后取最大的结果(正则表达式无法解决这种事情)。

于 2015-09-21T22:36:08.733 回答
1

如果附近有需要的nodule话,可以试试:

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

演示

如果出现以下情况,它将匹配:

  • 结节与 mm 中的值在同一个句子中([^.?!\n] 应该阻止它,但是像 Mr.,decimals 等这样的词会干扰匹配),你可以用.+?DEMO)替换它但是它可以在句子之间匹配
  • value 在 word nodule 之前或之后(在这个 orderer 中,如果之前有 value,它将首先匹配),
  • 值将被分组捕获:之前 - \1,之后 - \2,
  • 它应该与 g 和 i 模式一起使用

其他类似的解决方案是:

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

演示

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

于 2015-09-21T22:48:19.727 回答
1

让我们分解它,保留相关部分。到目前为止,您有 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}

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

你不能用正则表达式来做到这一点。循环在您的代码中找到最大的。


结果:

有了这些条件,我们有:

[\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. 寻找测量附近的日期。
于 2015-09-21T22:56:18.433 回答
1

关于这个问题,我最终使用 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}"

所以在这种情况下,我最终没有做负面的回顾,而是做了一个捕获组。

谢谢各位的意见。

于 2015-10-20T22:05:23.410 回答