什么是匹配一组几乎等效元素中的单个元素的正则表达式?

时间:2014-11-27 19:56:57

标签: regex

在以下内容中:

<page1 ...>
   ...
</page>

<page2 ...>
   ...
</page>

<page3 ...>
   ...
   <queue>...</queue>
   ...
</page>

如何找到最后一个元素(包含队列标记的元素)的匹配?

我试过了

(?s)<page.*?<queue>.*?</page>

但这符合整个内容。我一直在尝试使用前瞻,但无法弄清楚。

5 个答案:

答案 0 :(得分:2)

您可以将以下怪物用于您的特定用例:

<page(?:[^/]+/(?!page))+queue>(?:[^/]+|/(?!page))+/page>

..不确定这是否是学习正则表达式的最佳示例,在现实生活中用于解析XML绝对不是一个好主意。但这是可能的。不要忘记在引用/构造内的常规表达式的语言中\/ /.../ {。}}。

请参阅http://regex101.com/r/qZ0yR1/2处的技术说明。

逻辑如下:

  1. <page.../queue>.../page> - 获取包含队列结束标记的页面元素的内容

  2. [^/]+/(?!page) - 将所有文字匹配到下一个结束标记,但请确保它不是页面的结束标记

  3. (?:[^/]+/(?!page))+queue> - 根据需要重复上述匹配,直到结束标记为队列

  4. (?:[^/]+|/(?!page))+/page> - 然后根据需要重复多次,直到结束标记用于页面(我使用|作为(?:[^/]+/(?!page))+[^/]+/page>的快捷方式,因为第2点中的表达式。如果以下结束标记不是用于页面,则仅匹配文本,但我们需要在最后完全匹配该文本)

答案 1 :(得分:2)

你可以使用这种模式

(?:<page[^>]*>(?:(?!<queue>).)*?<\/page>)|(<page[^>]*>.*?<\/page>)  

Demo

这里的想法是首先使用不包含queue的标记,然后使用并捕获那些标记。

答案 2 :(得分:1)

这是我能够集中讨论的最简洁的方法:

<page(.(?!page))*<queue.*<\/page>

您需要设置DOTALL标志,并且整个匹配是您的目标。

请参阅demo

答案 3 :(得分:0)

您可以使用贪婪匹配(。*)来匹配最后一个标记的所有内容。

这是一个例子(原谅Java):

final String str = "<page1 foo='bar'>apple</page> <page2 foo='bar'>orange</page> <page3 foo='bar'>pear</page>";
final Pattern p = Pattern.compile(".*<page[^>]+>(\\w+)</page>$");
final Matcher matcher = p.matcher(str);
matcher.find();

// Prints pear
System.out.println(matcher.group(1));

此外,+1为'为什么选择正则表达式';正则表达式不适合这个问题。

答案 4 :(得分:0)

假设标签可能不是“队列”并且可能是其他任何内容,请尝试以下操作:

(?<=[>]).*(?=\<\/[\w]+\>([\n]?)(.*[\n])?\<\/page\>$)

这里的例子:

http://regex101.com/r/sN6aC5/1

这会使用前瞻性查找最后一个已关闭的标记</...>,后面跟着任何内容,然后是一个封闭的页面标记</page>,它是字符串的结尾。然后,使用lookbehind,匹配此最终关闭标记与之前的第一个>之间的所有内容(应该是最后一个开始标记)