【问题标题】:PCRE negative lookahead gives unexpected matchPCRE 负前瞻给出了意外的匹配
【发布时间】:2017-02-24 11:40:57
【问题描述】:

我想要一个 Perl 正则表达式来匹配 std::foo 但不匹配 std::foo::bar。这是我目前所拥有的:

/((?<!\w)([A-Za-z0-9_]+)::([A-Za-z0-9_]+))(?!:)/

这匹配 std::foo::barstd::fo,但我希望整个匹配失败,而不是部分匹配。

我真正想要什么正则表达式?

【问题讨论】:

  • [A-Za-z0-9_]如果字符集是纯ASCII,一般写成\w
  • 这是 Perl 还是 PCRE 问题?您似乎可以互换使用它们,但它们是不同的引擎

标签: regex perl pcre


【解决方案1】:

此解决方案在模式\w++foo 部分使用占有量词。这意味着它会在找到一系列“单词”字符后拒绝回溯,即使模式的其余部分 - 负前瞻 - 然后失败。我还必须更改否定的后视来拒绝单词字符或冒号:,以防止baz::std::foo之类的匹配

主要是对the answer from Sebastian Proske的整理。它使用\w 代替文字字符类,使用/x 修饰符添加布局,并删除不必要的括号。它还提供了一个工作示例

use strict;
use warnings 'all';
use feature 'say';

my $s = 'match std::foo but not match std::foo::bar.';

say $1 while $s =~ / (?<![\w:]) ( \w+::\w++) (?!:) /gx;

输出

std::foo

【讨论】:

    【解决方案2】:

    除了\b,您还可以:

    • 使用所有格匹配来避免回溯到foo((?&lt;!\w)([A-Za-z0-9_]+)::([A-Za-z0-9_]++))(?!:)
    • 将单词字符类添加到前瞻中,因此它不能回溯到foo((?&lt;!\w)([A-Za-z0-9_]+)::([A-Za-z0-9_]+))(?![:\w])

    【讨论】:

      【解决方案3】:

      只需在否定前瞻前添加\b,以确保存在单词边界,并且不要忘记在第一个否定前瞻中添加:。否则它会匹配第二部分。

      ((?<![:\w])([A-Za-z0-9_]+)::([A-Za-z0-9_]+))\b(?!:)
      

      只有在导入字符串前面没有非空格字符时才会匹配它。

      (?<!\S)([A-Za-z0-9_]+)::([A-Za-z0-9_]+)\b(?!:)
      

      DEMO

      【讨论】:

      • 你的第二个选择匹配不同的东西。我认为你应该解释一下。
      【解决方案4】:

      匹配整个字符串 std::foo::bar 而不是部分值 我们可以使用这个正则表达式

      ((\b(.+)\b)+?[::]{2}.+)

      它会给你两个匹配项

      • std::foo
      • std::foo::bar

      【讨论】:

      • [::]{2} 只不过是::。但无论如何,我看不出这个正则表达式如何回答这个问题。
      • 或者更准确地说,[::]{2}是一种奇怪的写法[:]{2},这是一种奇怪的写法:{2},这是一种奇怪的写法::
      猜你喜欢
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-02
      • 1970-01-01
      • 2014-04-19
      • 1970-01-01
      相关资源
      最近更新 更多