簡體   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