2011-12-08 100 views
0

對不起提前,這可能是一個有點挑戰性閱讀...正則表達式的問題與*懶惰

我試圖解析線(實際上從IMAP服務器主題行),看起來像這樣:

=?utf-8?Q?Here is som?= =?utf-8?Q?e text.?= 

這有點難看,但在上面的行中有兩個=?/?=對。 (總會有一對;理論上可能有很多。)在這兩個=?/?=對的每一對中,我想要提取第三個參數(由?分隔符定義)。 (第一對,它是「這裏是SOM」,並在第二個它的「電子文本。」)

下面是我使用的正則表達式:

=\?(.+)\?.\?(.*?)\?= 

我想它返回兩場比賽,每對=?/?=一對。相反,它將整條線路作爲單個匹配返回。我原以爲(.*?)中的?爲了讓*運算符懶惰,就不會​​發生這種情況,但顯然它不會。

有什麼建議嗎?

編輯:根據以下建議取代「。?」與「[^(\?=)]?」我現在試圖做的:

=\?(.+)\?.\?([^(\?=)]*?)\?= 

...但它不工作,要麼。 (我不確定[^(\?=)] *?是否是排除雙字符序列的正確方法,如「?=」。是否正確?)

回答

0

感謝大家的回答!這解決了我的問題,最簡單的表達是這樣的:

=\?(.*?)\?.\?(.*?)\?= 

這和我最初張貼表達之間的唯一區別是增加了一個? (非貪婪)運營商在第一個「。*」。關鍵,我忘了它。

1

試試這個:

\=\?([^?]+)\?.\?(.*?)\?\= 

我改變了.+[^?]+,這意味着

+0

有效的建議,但你修改了錯誤的參數:它應該是第二組圓括號,而不是第一組。 (參見上面我的編輯。)另外,結尾分隔符是一個?=,而不僅僅是一個?。我該如何測試?謝謝。 –

1

一種解決方案 「除了?一切」:

=\?(.*?)\?=\s*=\?(.*?)\?= 

說明:

=\? # Literal characters '=?' 
(.*?) # Match each character until find next one in the regular expression. A '?' in this case. 
\?= # Literal characters '?=' 
\s* # Match spaces. 
=\? # Literal characters '=?' 
(.*?) # Match each character until find next one in the regular expression. A '?' in this case. 
\?= # Literal characters '?=' 

測試在「Perl的程序:

use warnings; 
use strict; 

while (<DATA>) { 
    printf qq[Group 1 -> %s\nGroup 2 -> %s\n], $1, $2 if m/=\?(.*?)\?=\s*=\?(.*?)\?=/; 
} 

__DATA__ 
=?utf-8?Q?Here is som?= =?utf-8?Q?e text.?= 

運行:

perl script.pl 

結果:

Group 1 -> utf-8?Q?Here is som                                                    
Group 2 -> utf-8?Q?e text. 

編輯評論

我會使用全局修飾符/.../g。正則表達式是:

/=\?(?:[^?]*\?){2}([^?]*)/g 

說明:

=\?    # Literal characters '=?' 
(?:[^?]*\?){2} # Any number of characters except '?' with a '?' after them. This process twice to omit the string 'utf-8?Q?' 
([^?]*)   # Save in a group next characters until found a '?' 
/g    # Repeat this process multiple times until end of string. 

Perl腳本測試:

use warnings; 
use strict; 

while (<DATA>) { 
     printf qq[Group -> %s\n], $1 while m/=\?(?:[^?]*\?){2}([^?]*)/g; 

} 

__DATA__ 
=?utf-8?Q?Here is som?= =?utf-8?Q?e text.?= =?utf-8?Q?more text?= 

運行和結果:

Group -> Here is som 
Group -> e text. 
Group -> more text 
+0

並不總是有兩對=?/?=,這就是你的解決方案似乎是硬編碼的情況。大多數時候,只有一個,偶爾兩個,理論上是無限的數字。是否有解決此問題的快速解決方案?謝謝! –

+0

我編輯了我的答案。 – Birei

1

中好的做法我體驗我不要使用.*?,而是使用*而不使用?,但是要改善角色類。在這種情況下[^?]*匹配一系列非問號標記字符。 ?

你也可以這樣搭配更復雜endmarkers,例如,在這種情況下,您的最終限制器=,所以你想匹配nonquestionmarks,其次爲questionmarks不等於:

([^?]*\?[^=])*[^?]* 

在這一點上,它變得更難以選擇。我喜歡這個解決方案更嚴格,但在這種情況下可讀性會下降。

+0

有效的建議,但結尾分隔符是一個?=,而不僅僅是一個?我該如何測試? (看我上面的編輯。)謝謝。 –

+0

增加了一些更多的解釋。你不能在一個字符類中同時匹配多個字符,''[^(\?=)]'''實際上是不匹配括號,反斜槓,questionmark和等號的字符類。 – markijbema