我試圖做一個非貪婪負的比賽,我需要捕獲它。我在Python中使用這些標誌,re.DOTALL | re.LOCALE | re.MULTILINE,做一些文本文件「數據庫」,其中每個領域開始與一個反斜槓一個新行的多行清理。每條記錄都以\ lx字段開頭。捕獲在Python正則表達式匹配負
\lx foo
\ps n
\nt note 1
\ps v
\nt note
\ge happy
\nt note 2
\ge lonely
\nt note 3
\ge lonely
\dt 19/Dec/2011
\lx bar
...
我想確保每個\ GE領域有它上面某處\ PS場的紀錄,一對一內。目前,一個\ ps後面往往有幾個\ ge,因此需要複製下來,就像上面兩個孤獨的\ ge一樣。
這裏最需要的邏輯:之後的任何\ PS場,但遇到另一個\ PS或\ LX之前,找到\ GE,然後找到另一個\ GE。捕獲所有內容,以便可以將\ ps字段複製到第二個\ ge之前。
這是我的非功能性的嘗試。替換此:
^(\\ps\b.*?\n)((?!^\\(ps|lx)*?)^(\\ge.*?\n)((?!^\\ps)*?)^(\\ge.*?\n)
與此:
\1\2\3\4\1\5
我甚至在一個很小的文件(34線長),得到一個內存錯誤。當然,即使這個工作,我不得不多次運行它,因爲它只是試圖處理第二\ GE,而不是第三或第四個。所以這方面的任何想法都會讓我感興趣。
更新:艾倫摩爾的解決方案效果很好,雖然有些案例需要稍微調整。可悲的是,我不得不關閉DOTALL否則我不能防止第一*包括後續\ PS域 - 甚至與非貪婪。*?形成。但我很高興在正則表達式點信息中瞭解了(?s)修飾符。這允許我關閉DOTALL,但仍然在其他正則表達式中使用它,它對於是必不可少的。
這是建議的正則表達式,凝聚到單行格式,我需要:
^(?P<PS_BLOCK>(?P<PS_LINE>\\ps.*\n)(?:(?!\\(?:ps|lx|ge)).*\n)*\\ge.*\n)(?P<GE_BLOCK>(?:(?!\\(?:ps|lx|ge)).*\n)*\\ge.*\n)
這工作,但是當我修改上面的例子中,插入上面的「記2」的\ PS。它也將\ lxs和\ ge2視爲\ lx和\ ge(需要一些\ b)。所以,我去一個稍微調整了版本:
^(?P<PS_BLOCK>(?P<PS_LINE>\\ps\b.*\n)(?:(?!\\(?:ps|lx|ge)\b).*\n)*\\ge\b.*\n)(?P<AFTER_GE1>(?:(?!\\(?:ps|lx|ge)\b).*\n)*)(?P<GE2_LINE>\\ge\b.*\n)
這種替換字符串:
\g<PS_BLOCK>\g<AFTER_GE1>\g<PS_LINE>\g<GE2_LINE>
再次感謝!
你試圖做的事是不可能的與一個常規的語言(*「上面的某處」*種類的那樣)。您應該簡單地編寫一個解析器或其他東西,並在運行中創建正確的輸出。 – poke 2012-08-12 20:32:27
我認爲這是正則表達式是錯誤的工具。 – MRAB 2012-08-12 22:08:07
我同意這是推動極限,但看到我回答比約恩的答案是因爲我的原因。 – 2012-12-13 16:32:11