2009-03-03 24 views
4

好吧,我有一個多行字符串,我正試着做一些清理工作。正則表達式替換,但只在兩個模式之間

每一行可能是也可能不是大塊引用文本的一部分。例如:

This line is not quoted. 
This part of the line is not quoted 「but this is.」 
This one is not quoted either. 
「This entire line is quoted」 
Not quoted. 
「This line is quoted 
and so is this one 
and so is this one.」 
This is not quoted 「but this is 
and so is this.」 

我需要一個正則表達式替換,將未包裹的硬包裹引述線,即,替換爲「\ r \ n」個具有空間,但只之間的彎引號。

下面是它看起來應該更換後:(注意最後兩行是如何多行輸入文本)

This line is not quoted. 
This part of the line is not quoted 「but this is.」 
This one is not quoted either. 
「This entire line is quoted」 
Not quoted. 
「This line is quoted and so is this one and so is this one.」 
This is not quoted 「but this is and so is this.」 

約束

  • 理想的情況下需要一個正則表達式替換調用
  • 使用.NET RegEx庫
  • 報價是總是開始/結束捲菸報價,而不是簡單的雙'剔'(「),這應該使這更容易一些。

重要的約束

這不是直接的.NET代碼,我填充的「searchfor/replacewith」字符串,然後通過RegEx.Replace稱爲表。我沒有通過捕獲組添加自定義代碼像匹配評估者,循環的能力,等等​​。

當前的答案到目前爲止,沿着線的東西:

r.Replace("(?<=「)\r\n(?=」)", " ") 

很顯然,我不是甚至關閉。

相同的邏輯可以應用於編程代碼中塊註釋的顏色編碼 - 塊註釋內的任何內容都不會與註釋外的內容一樣對待。 (代碼是有點棘手,因爲開始/結束塊註釋分隔符也可以合法存在於一個文字字符串中,這個問題我不必在這裏處理。)

+0

你能提供任何約束的原因,特別是前兩個? – MarkusQ 2009-03-03 21:45:09

+0

補充...這不是自定義代碼,它是我編寫的通用解析/清理工具,它是從數據庫進行表驅動的。對於爲這個特定問題編寫一次性代碼並不容易。 – richardtallent 2009-03-03 22:55:35

回答

4

假設所有彎引號是適當的平衡,這正則表達式應該做你想要什麼:

@"[\r\n]+(?=[^「」]*」)" 

[\r\n]+將匹配任何類型的一個或多個行分隔符 - UNIX(\ n ),DOS(\ r \ n)或更舊的Mac(\ r)。然後,前瞻聲稱前面有一個近似報價,並且在這裏和那裏之間沒有公開引用。那麼你的替換文字可以是一個簡單的空格字符。

0

所以要做的事情是找到一個字符串開始開頭引號後跟一個字符串而不是包含一個結尾引號或任何\ r \ n字符,後跟一系列一個或多個\ r \ n字符,捕獲除終端之外的所有內容\ r \ n個字符,並用捕獲的部分替換整個匹配。

- MarkusQ

+0

因此,您建議的是:(「[^ \ r」] +)\ r \ n替換爲$ 1 [] 關閉!這將捕獲引用文本中的第一個換行符,但不包括其他任何替換文件。替換不是遞歸的。 – richardtallent 2009-03-03 22:13:17

0

我認爲最簡單的方法是將引用的部分與「(?s:.*?)」匹配和使用MatchEvaluator,以消除任何換行符。該MatchEvaluator代碼可能是那樣簡單

Replace(@"\s+", " "); 

你可以,當然,完善這一隻匹配報價的部分,實際上包含換行符,而這些部分而不是所有的空格內只更換換行符,但它可能不值得努力。

+0

我正在編程一組RegEx調用,這些調用都是以特定順序從表中創建的,而不是在此編寫自定義代碼。 – richardtallent 2009-03-03 22:52:16

+0

好的,然後看看我的其他答案。 – 2009-03-04 01:26:26

0

你不能在你描述的範圍內做你想做的事。

證明:

  • 您的固定替換表將執行呼叫固定數量的更換(稱之爲N)
  • 每更換隻能消除換行符固定數量(電話這個數字m)。

因此

  • 與M * n + 1個換行甲引述塊將不能正確處理。

您需要增加設置的權力(例如,通過允許更復雜的替換,遞歸替換,無限重複標誌或...?)或接受這個任務無法完成的事實由你的引擎。

- MarkusQ

+0

如果我需要檢查平衡的引號,我認爲你會是正確的,我越看到各種建議。艾倫提出了一個基於我的具體使用案例的解決方案,我可以依賴於引用的平衡。感謝所有的幫助! – richardtallent 2009-03-04 02:49:49

1

注意:爲了測試正則表達式我用http://gskinner.com/RegExr/這是非常有用的。

我不認爲你可以寫一個表達式來替換未定義數量的換行符。但是,您可以編寫一個表達式來替換一個或多個表達式,並反覆運行或編寫它來處理您在一個引用部分中所具有的最大換行數。

首先,您需要單行模式,以便表達式匹配整個輸入字符串而不是逐行。你應該在你的表達開始將其打開:

(?s) 

然後,你要查找的背後則表達式匹配的起始報價:

(?<=「) 

而且先行匹配最終報價:

(?=」) 

現在,一個表達式匹配一些文本,然後換行,然後一些文本:

([^」\r]*)\r?([^」\r]*) 

請注意,對於換行符周圍的文本位有兩個捕獲組,因此您可以將該文本包含在替換表達式中。這將匹配引號內只有一個換行符的文本。爲了擴大這兩個新行,只需添加一個可選的換行和可選的以下文字:

(?s)(?<=「)([^」\r]*)\r?([^」\r]*)\r?([^」\r]*)(?=」) 

你可以擴展,以儘可能多的換行,你認爲可能會出現匹配。不完美,但也許是足夠的。或者,如果您可以反覆在文字上運行表達式,則只需一次替換一個。

離開你的表情是這樣的:

r.Replace("(?s)(?<=「)([^」\r]*)\r?([^」\r]*)", "$1 $2") 

(這是不太正確的,因爲它會文本後添加一個空格,即使組的兩個不匹配......但它是一個開始)