正则表达式以任何顺序匹配多个捕获组

时间:2015-09-30 22:15:07

标签: regex perl capture regex-group

鉴于下面的示例字符串,我试图捕获'to','from','subject'和'type'字段并以不同的格式将它们吐出来。问题是这些字段(to,from等)可以按任何顺序排列。

示例STRING to REGEX ON

<cfmail to="#toAddr#" from="#fromAddress" 
  subject="#subject#" type="html">
    #emailMsg#
</cfmail>

输出我正在寻找

to:toAddr, from:fromAddress, subject:subject

如果我知道我感兴趣的那些领域的顺序总是一样的话那么这很容易,但是我很难知道如何进行这种匹配,例如,'from'来自'之前'到“

我现在拥有的perl单线程(仅用'to'和'subject'进行测试)

s/<cfmail.*?((to)="(.*?)")|((subject)="(.*?)").*<\/cfmail>/\1:\2, \3:\4/g

最终匹配'to'值但停在那里,我没有获得'subject'值的任何内容。我已经尝试了几种变体,我改变了匹配组设置等,但没有运气。

1 个答案:

答案 0 :(得分:2)

您是否需要允许缺少字段(例如,没有type字段)?那四个以外的其他领域怎么样?如果你对这两个问题都回答“否”,那么这个正则表达式应该可以解决问题:

s!<cfmail(?:\s+to="(?<to>[^"]+)"|\s+from="(?<from>[^"]+)"|\s+subject="(?<subject>[^"]+)"|\s+type="(?<type>[^"]+)")+>.*?</cfmail>!to:$+{to}, from:$+{from}, subject:$+{subject}!gs

以下是正则表达式,更具可读性:

<cfmail
(?:
  \s+to="(?<to>[^"]+)"
  |
  \s+from="(?<from>[^"]+)"
  |
  \s+subject="(?<subject>[^"]+)"
  |
  \s+type="(?<type>[^"]+)"
)+
>
.*?</cfmail>

...和DEMO

你实际上非常接近;交替是关键。你只需要添加一个量词。

请注意,我从字段名称中删除了捕获组。您已经知道了名称,只需要将它们与正确的值配对即可。命名组使这更容易。