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

regex match multiple capture groups in any order

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

要使用正则表达式的示例字符串

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

我正在寻找的输出

to:toAddr, from:fromAddress, subject:subject

如果我知道我感兴趣的那些字段的顺序总是相同的,那么这很容易,但是我不知道如何进行匹配,例如,'from'在 'to'

之前

我现在拥有的 perl 单行代码是(仅使用 'to' 和 'subject' 进行测试)

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

这最终与 'to' 值匹配,但停在那里,我没有得到 'subject' 值的任何信息。我已经尝试了几种变体,我改变了匹配组设置等,但没有成功。

您是否需要允许缺少字段(例如,没有 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

你们其实很接近;交替是关键。您只需要添加一个量词。

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