[英]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.