正则表达式组中的多个匹配项?

时间:2009-08-21 17:49:42

标签: php regex

我需要匹配XML属性中出现的所有'标签'(例如%thisIsATag%)。 (注意:我保证会收到有效的XML,因此不需要使用完整的DOM遍历)。我的正则表达式正在工作,除非单个属性中有两个标记,只返回最后一个。

换句话说,这个正则表达式应该找到tag1,tag2,...,tag6。但是,它省略了tag2和tag5。

这是一个有趣的小测试工具(PHP):

<?php

$xml = <<<XML
<data>
 <slideshow width="625" height="250">

  <screen delay="%tag1%">
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize="32" fontstyle="bold" text="Screen One!%tag2% %tag3%"/>
   </text>
  </screen>

  <screen delay='%tag4%'>
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize='32' fontstyle='bold' text='Screen 2!%tag5%%tag6%'/>
   </text>
  </screen>

  <screen>
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize="32" fontstyle="bold"  text="Screen Tres!"/>
   </text>
  </screen>

  <screen>
   <text x="30%" y="50%" animatefromx="800">
    <line fontsize="32" fontstyle="bold"  text="Screen FOURRRR!"/>
   </text>
  </screen>

 </slideshow>
</data>
XML;

$matches = null;
preg_match_all('#<[^>]+("([^%>"]*%([^%>"]+)%[^%>"]*)+"|\'([^%>\']*%([^%>\']+)%[^%>\']*)+\')[^>]*>#i', $xml, $matches);

print_r($matches);
?>

谢谢! :)

3 个答案:

答案 0 :(得分:2)

这是:

(%[a-zA-Z0-9]+%)

还不够?在您的示例中,标记不会出现在属性值之外的任何位置 - 可以吗?

答案 1 :(得分:2)

%\ w +%将是一种更简单的方法。

答案 2 :(得分:2)

您要做的是从每个正则表达式匹配多次匹配的组中恢复中间捕获。据我所知,只有.NET和Perl 6提供了这种功能。您必须分两个阶段完成这项工作:将属性值与其中的一个或多个%tag%序列进行匹配,然后分解各个序列。

您似乎并不关心值与哪个XML标记或属性相关联,因此您可以使用此更简单的正则表达式来查找其中包含%tag%个序列的值:

'#"([^"%<>]*+%[^%"]++%[^"]*+)"|\'([^\'%<>]*+%[^%\']++%[^\']*+)\'#'

编辑:该正则表达式捕获组1或组2中的属性值,具体取决于它使用的引号。这是另一个合并备选方案的版本,因此它总是可以保存第2组中的值:

'#(["\'])((?:(?![%<>]|\1).)*+%(?:(?!%|\1).)++%(?:(?!\1).)*+)\1#'