PHP PCRE正则表达式,模式中有多个SKIP FAIL

时间:2017-11-11 17:27:08

标签: php regex encoding pattern-matching pcre

我有一个简单的字符串:

$string = '--#--%--%2B--';

除了%字符和-形式的三元组外,我想对所有字符进行百分比编码(包括“孤独”%xy)。所以我写了以下模式替代方案:

$pattern1 = '/(?:[\-]+|%[A-Fa-f0-9]{2})(*SKIP)(*FAIL)|./us';
$pattern2 = '/(?:[\-]+)(*SKIP)(*FAIL)|(?:%[A-Fa-f0-9]{2})(*SKIP)(*FAIL)|./us';

请注意使用(多个)(*SKIP)(*FAIL)(?:)

匹配和替换的结果是相同的 - 也是正确的:

--%23--%25--%2B--

我想问一下:

  • 这两种模式是否相同?如果不是,哪一个适合用于url编码?能用几句话解释一下,为什么?
  • 你会建议其他选择(暗示回溯控制动词),还是我的模式是一个不错的选择?
  • 我是否可以在整个(选定)模式中仅应用一个(?:),即使(多个)(*SKIP)(*FAIL)会在其中?

我知道我一次要求更多问题,要求你多一点。请接受我的道歉!非常感谢你。

P.S:我已经使用以下PHP代码进行了测试:

$result = preg_replace_callback($patternX, function($matches) {
    return rawurlencode($matches[0]);
}, $string);
echo $result;

1 个答案:

答案 0 :(得分:1)

首先,两种模式都利用了SKIP-FAIL PCRE动词序列,这是一个众所周知的“技巧”,可以匹配某些文本,跳过它。有关更多详细信息,请参阅How do (*SKIP) or (*F) work on regex?

这两种模式产生相同的结果,(?:[\-]+|%[A-Fa-f0-9]{2})(*SKIP)(*FAIL)匹配[\-]+%[A-Fa-f0-9]{2},然后跳过匹配,(?:[\-]+)(*SKIP)(*FAIL)|(?:%[A-Fa-f0-9]{2})(*SKIP)(*FAIL)首先尝试匹配[\-]+如果找到则跳过它,然后尝试匹配%[A-Fa-f0-9]{2}并跳过匹配(如果找到)。第二种模式中的(?:...)非捕获组是多余的,因为内部没有交替,并且组未被量化。您可以在模式中使用任意数量的(*SKIP)(*FAIL),只需确保在|之前使用它们以跳过相关匹配。

当您想要匹配特定上下文中的某些文本时,如果要在之后跳过/“避免”使用char,并且后面跟着某些字符,或者当您使用时,则使用SKIP-FAIL技术需要“避免”匹配整个序列的字符,就像在这种情况下一样,因此,SKIP-FAIL很好用。