【问题标题】:Regex non-capturing group is capturing正则表达式非捕获组正在捕获
【发布时间】:2011-05-05 15:26:28
【问题描述】:

我有这个正则表达式

(?:\<a[^*]href="(http://[^"]+?|[^"]+?\.pdf)"+?[^>]*?)>

此正则表达式的重点是捕获具有以“http://”开头或以“.pdf”结尾的 href 的锚点的每个结束标记 ('>')。

正则表达式有效,但它正在捕获锚的第一部分,我绝对不需要捕获。

在以下示例中,除了第二个(这很好)之外,所有示例都匹配,但只应捕获最后一个括号,事实并非如此。

<a href="http://blabla">omg</a>
<a href="blabla">omg</a>
<a href="http://blabla.pdf">omg</a>
<a href="/blabla.pdf">omg</a>

例如:如果我们取第一个匹配项:

<a href="http://blabla">

我只想捕获最后一个括号(我用括号括起来的那个):

<a href="http://blabla"(>)

那么为什么非捕获组正在捕获?而我怎么只能抓住锚的最后一个括号

即使我将正则表达式简化为以下内容,它仍然不起作用

(?:\<a[^*]href="http://[^"]+"+[^>]*)(>)

谢谢,

【问题讨论】:

  • 您能否提供一个示例来说明您试图在字符串中捕获的内容?
  • 我认为更好的方法是使用 HTML 解析器并将正则表达式应用于每个 href 属性。
  • @mikerobi 可能会很好,问题是我唯一的工具是一个简单的查找和替换我无法隔离任何捕获的组,匹配需要是我想要替换的字符串
  • 您使用什么语言? PHP?
  • 另外,为什么加号 (+) 和星号 (*) 后面有问号 (?)?

标签: html regex anchor


【解决方案1】:

将你的正则表达式重写为:

(?:\<a[^*]href="(?:http://[^"]+?|[^"]+?\.pdf)"+?[^>]*?)(>)
   non capture __^^                                    ^ ^
                                             capture __|_|

正如托尼·卢卡萨维奇所说,有一个不必要的非捕获组,而且,没有必要逃跑&lt;,所以变成了:

  <a[^*]href="(?:http://[^"]+?|[^"]+?\.pdf)"+?[^>]*?(>)
non capture __^^                                    ^ ^
                                          capture __|_|

【讨论】:

  • 在他真正想要捕获的最后一个括号之前,你有一个不必要的非捕获组。
  • @Tony Lukasavage:你是对的,但它有效,我刚刚采用了 OP 的正则表达式。它不值得一票否决。
【解决方案2】:

您将两个不同的概念混为一谈:捕获消费。正则表达式通常会消耗它们匹配的任何东西。这就是他们的工作方式。此外,大多数正则表达式风格都允许您使用capturing groups 来提取整体匹配的特定部分。 (整体匹配通常被称为第零个捕获组,但这只是一个比喻。)

听起来您正在尝试匹配整个 &lt;A&gt; 标签,但只使用最后一个 &gt;。这在大多数正则表达式风格中是不可能的,包括 JavaScript。但是如果你使用 Perl 或 PHP,你可以使用\K 来欺骗匹配开始位置:

(?i)<a\s+[^>]+?href="http://[^"]+"[^>]*\K>

而在 .NET 中,您可以使用后视(与前瞻一样,匹配而不消耗):

(?i)"(?<=<a\s+[^>]+?href="http://[^"]+"[^>]*)>

在支持lookbehinds 的其他风格中,大多数都对它们设置了限制,使其无法用于此任务。

【讨论】:

  • 一年后回顾这个回复,在这个主题上有更多的经验。这就是我一直在寻找的答案。
【解决方案3】:

如果我正确理解您只想匹配作为结束锚标记一部分的大于号 (&gt;),那么应该这样做:

\<a[^*]href="(http://[^"]+?|[^"]+?\.pdf)"+?[^>]*?(>)

【讨论】:

    【解决方案4】:

    如果我正确理解您的要求...

    \<a[^*]href="(?:http://[^"]+?|[^"]+?\.pdf)"+?[^>]*?(>)
    

    【讨论】:

    • 我的和 compeek 的正则表达式都将执行您正在寻找的模式匹配,正如我们所理解的那样。究竟是什么不适合它?
    • 好吧,除非我使用的正则表达式测试器是错误的。我正在使用这个regexpal.com
    • 我使用的是完全相同的测试仪,它对我来说工作得很好。 :\
    • 只是高亮右括号?
    • 我认为使用lookbehind 可以做到,但JavaScript 不支持lookbehinds。由于您使用的是查找和替换工具,甚至无法编写任何代码来解决它,我不确定是否可以满足您的需求。
    【解决方案5】:

    您的括号围绕标签本身和 href 的内容,所以这就是将被捕获的内容。如果您需要捕获结束 > 然后将括号放在它周围。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 2019-01-12
    • 1970-01-01
    • 2015-07-24
    • 2021-12-11
    相关资源
    最近更新 更多