PHP 模式中有多个 SKIP FAIL 的 PCRE 正则表达式
PHP PCRE regex with multiple SKIP FAIL in a pattern
我有一个简单的字符串:
$string = '--#--%--%2B--';
我想对所有字符(包括 "lonely" %
)进行百分号编码,-
字符和 %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;
首先,这两种模式都利用众所周知的 SKIP-FAIL PCRE 动词序列 "trick" 来匹配一些文本,然后 跳过 它。有关详细信息,请参阅 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)
,只需确保在 |
之前使用它们以跳过相关匹配。
SKIP-FAIL 技术用于当你想在特定上下文中匹配某些文本时,当一个字符应该被跳过时/"avoided" 如果它在前面 和 后面一些字符,或者当你需要 "avoid" 匹配整个字符序列时,就像在这种情况下,因此,SKIP-FAIL 很好用。
我有一个简单的字符串:
$string = '--#--%--%2B--';
我想对所有字符(包括 "lonely" %
)进行百分号编码,-
字符和 %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;
首先,这两种模式都利用众所周知的 SKIP-FAIL PCRE 动词序列 "trick" 来匹配一些文本,然后 跳过 它。有关详细信息,请参阅 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)
,只需确保在 |
之前使用它们以跳过相关匹配。
SKIP-FAIL 技术用于当你想在特定上下文中匹配某些文本时,当一个字符应该被跳过时/"avoided" 如果它在前面 和 后面一些字符,或者当你需要 "avoid" 匹配整个字符序列时,就像在这种情况下,因此,SKIP-FAIL 很好用。