正则表达式:查找特定文本周围的第一个标记

时间:2011-10-26 09:12:47

标签: html regex

我有一些我知道的文字,我需要找到第一个标签,并在该文本周围定义类。

示例:

<table>
  <td class="foo">
    <p>...</p>
  </td>
  <td class="bar">
    <p>Text i dont know</p>
    <p>Text i know</p>
    <p>Text i dont know</p>
  </td>
</table>

我尝试了很多东西。我知道如何找到结束标记,但是当我尝试查找开始标记时,我的正则表达式返回td类为“foo”而不是类“bar”。

我将非常感谢你的帮助。

编辑: 我想在python中做到这一点。我提供了问题的弱规范。该标记不必是标记,它可以是指定类的任何标记。我不想用正则表达式“解析”html,但我没有看到任何其他方式如何在不使用正则表达式的情况下执行此类操作。 我需要的是在该标签周围找到具有指定类的第一个标签。

5 个答案:

答案 0 :(得分:2)

您必须在多行或dotall模式下执行此操作,其中点.与换行符匹配。

<(\w+)[^>]*class="([^"]*)"[^>]*>(?:(?!<\/\1).)*Text i know(?:(?!<\/\1).)*<\/\1>

构造(?!<\/\1).用于匹配任何字符,但正在启动一个名称与之前匹配的结束标记的字符除外。

请注意,我已在此处转义了/斜杠,并且我没有使用双引号。你可能不得不以不同的方式逃避。我tested itrubular

答案 1 :(得分:2)

好的,我们走了!

(?s)<(\w+)[^>]*\sclass="[^"]*"[^>]*>(?:(?!</?\1\b|<\w+[^>]*\sclass="[^"]*"[^>]*>)(?:Text i know()|.))*</\1>\2

通常的方法是只匹配一个名字不提前知道的元素(我们假设(?s)从这里开始):

<(\w+)[^>]*>(?:(?!</?\1\b).)*</\1>

前瞻 - (?!</?\1\b) - 如果碰巧是标记的第一个字符(打开或关闭),并且与当前匹配的元素同名,则阻止点匹配。在这种情况下,也需要class属性,因此第一部分变为:

<(\w+)[^>]*\sclass="[^"]*"[^>]*>

这个问题并不完全清楚,但我假设您希望将最直接的封闭元素与class属性相匹配。也就是说,在以下文字中,您希望匹配td.yes-me元素, table元素。

<table class="not-me">
  <td class="not-me-either">
    <p>Text i dont know</p>
  </td>
  <td class="yes-me">
    <p>Text i dont know</p>
    <p>Text i know</p>
    <p>Text i dont know</p>
  </td>
  <td>
    <p>Text i dont know</p>
  </td>
  <td>
    <p>Text i dont know</p>
    <p>Text i know</p>
    <p>Text i dont know</p>
  </td>
</table>

这意味着前瞻也必须排除任何带有class属性的开始标记。它现在变成了这个:

(?!</?\1\b|<\w+[^>]*\sclass="[^"]*"[^>]*>)

最后,元素的内容应该包含您的目标文本(Text i know)。在前瞻成功之后,我们尝试匹配;如果我们成功,它后面的空捕获组会捕获一个空字符串。否则,点消耗下一个字符并重复该过程。

当完成所有匹配并且匹配结束标记时,反向引用\2确认已看到目标文本。由于该组不消耗任何字符,因此反向引用也不会,但如果组参与了比赛,它仍会报告成功。

Back-assertions(我喜欢称之为)并不适用于所有版本,并且在任何版本中都不支持正式,但它们适用于大多数Perl派生的风味,包括Python。 (最值得注意的例外是JavaScript和其他ECMAScript实现。)

如果你对此答案的反应是非常恐怖的,不要担心,我不会被冒犯。 ;)鼓励你更努力地寻找不涉及正则表达式的解决方案也是一个成功的结果。 (但确实有效!)

答案 2 :(得分:0)

<td class=\"(\w+)\">.*?TEXT_YOU_KNOW.*?</td>

如果您使用的是Java,或者您使用的语言等效,则必须处于DOTALL模式,因为点需要匹配行终止符。

编辑:匹配任何标记如何:

class=\"(\w+)\".*?TEXT_YOU_KNOW

答案 3 :(得分:0)

怎么样:

<(?<tagname>\w+)\s*class="[^"]*"[^>]*>Text which is known</\1>

答案 4 :(得分:0)

如果可以,请使用XDocument。

可以更轻松地浏览您的HTML

(不要忘记在您的HTML中添加ROOT标记)

也许你必须在你的HTML中做一些解析工作,但是使用这么简单的HTML,没有问题。