2011-12-08 55 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