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

标签 regex perl capture regex-group

鉴于下面的示例字符串,我 try catch “收件人”、“发件人”、“主题”和“类型”字段,并以不同的格式将它们吐出。问题是这些字段(收件人、发件人等)可以按任何顺序排列。

正则表达式的示例字符串

<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>/\1:\2, \3:\4/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

你们实际上已经很接近了;交替是关键。您只需要添加一个量词。

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

关于正则表达式以任意顺序匹配多个捕获组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32876469/

相关文章:

css - 如何将 em/rem 转换成 px?

ios - Kofax Capture Mobile SDK 是否有适用于 iOS 的试用版?

c - 如何使用libpcap嗅探PPP数据包?

javascript - 为什么正则表达式不匹配所有数字而不是匹配字符串末尾的数字?

python - 正则表达式匹配句点但不匹配数字之间

regex - 使用 sed,将特定字符串下方的部分行写入两个不同的变量

c++ - MediaCapture如何使用录音

python - 仅替换匹配表达式中的特定组

regex - 如何将所有 #include "...\..."中的反斜杠替换为正斜杠

xml - 配置 Perl 脚本为超大网站自动生成 XML 站点地图