PCRE负向前瞻产生意外匹配

时间:2017-02-24 11:40:58

标签: regex perl pcre

我希望Perl正则表达式与std::foo匹配但不匹配std::foo::bar。这就是我到目前为止所做的:

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

这与std::foo::bar匹配std::fo,但我希望此输入的整个匹配失败,而不是部分匹配。

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

4 个答案:

答案 0 :(得分:4)

此解决方案在模式foo的{​​{1}}部分使用所有格量词。这意味着它会在找到一系列“单词”字符后拒绝回溯,即使其余模式 - 负面预测 - 也会失败。我还必须更改否定后备以拒绝单词字符或冒号\w++ 以防止:之类的内容匹配

它主要是the answer from Sebastian Proske的整理。它使用baz::std::foo而不是文字字符类,使用\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;

答案 1 :(得分:1)

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

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

OR

仅当导入字符串前面没有非空格字符时才会匹配。

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

DEMO

答案 2 :(得分:1)

除了\b之外,您还可以:

  • 使用所有格匹配以避免回溯到foo((?<!\w)([A-Za-z0-9_]+)::([A-Za-z0-9_]++))(?!:)
  • 将单词character class添加到前瞻,因此无法回溯到foo((?<!\w)([A-Za-z0-9_]+)::([A-Za-z0-9_]+))(?![:\w])

答案 3 :(得分:-1)

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

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

它会给你两场比赛

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