PHP正则表达式中的反向引用条件是如何工作的?
我的要求如下: 如果字符串包含单词cat,则必须匹配cat。 但是,如果单词cat前面有单词dog,那么cat后面还必须有dog,并且所有3个单词都必须匹配。 这意味着不能匹配字符串dog cat,因为第二个dog不存在。 因此,我用PHP编写了以下正则表达式。它包含一个反向参考条件:PHP正则表达式中的反向引用条件是如何工作的?,php,regex,Php,Regex,我的要求如下: 如果字符串包含单词cat,则必须匹配cat。 但是,如果单词cat前面有单词dog,那么cat后面还必须有dog,并且所有3个单词都必须匹配。 这意味着不能匹配字符串dog cat,因为第二个dog不存在。 因此,我用PHP编写了以下正则表达式。它包含一个反向参考条件: $ptn = '@' . // PHP delimiter '(dog\s*)?' . // dog
$ptn = '@' . // PHP delimiter
'(dog\s*)?' . // dog
'cat\s*' . // cat
'(?(1)dog)' . // backreference cond
'@'; // PHP delimiter
正则表达式满足第1条要求:
$str1b = 'cat';
preg_match($ptn, $str1b, $matches);
print_r($matches);
O/p为:
数组[0]=>cat
正则表达式还满足第2条要求:
$str1a = 'dog cat dog';
preg_match($ptn, $str1a, $matches);
print_r($matches);
O/p为:
数组[0]=>狗猫狗[1]=>狗
但是,我想问为什么数组包含2个元素?是因为正则表达式有2个子表达式吗
现在谈谈要求3。以下数据对其进行了测试:
$str1c = 'dog cat';
preg_match($ptn, $str1c, $matches);
print_r($matches);
此处的O/p为:
数组[0]=>cat
在这里,我想问:
为什么猫是配对的?因为前面有狗,所以后面也应该有狗,这会导致一场比赛;否则就不应该发生匹配
这就是正则表达式的工作原理吗
我如何达到我的3个要求
这是我的建议
我正在考虑只使用PHP的解决方案。在使用捕获组时,您将获得2个匹配项 使用您尝试的模式dog\s*?cat\s*?1dog,您可以得到一个猫对狗猫的匹配 这是因为模式可以选择性地匹配狗。若有狗,它会被抓获,然后尝试匹配猫 然后在if子句中声明:如果我们有第1组,则匹配狗。发生的情况是,如果组1中没有匹配项,它仍然可以匹配cat,因为捕获组1是可选的 因此,在“狗-猫”中,它最终无法与“狗”匹配,但当尝试从“猫”开始时,它可以与后面的“猫”匹配 如果你想匹配所有3个单词“狗-猫-狗”或只匹配一只猫,而你不想匹配“狗-猫”,你可以使用
\b(?:dog cat dog|dog cat\b(*SKIP)(*F)|cat)\b
\b防止部分匹配的单词边界
?:非捕获组
狗猫狗狗比赛
|或
狗猫\b*跳过*F如果狗猫跳过比赛
|或
猫只会数学
关闭非捕获组
\b单词边界
|
比如说
$strings = [
"cat",
"dog cat dog",
"dog cat",
"cat dog",
"this cat cat is a test dog cat dog cat"
];
$pattern = "/\b(?:dog cat dog|dog cat\b(*SKIP)(*F)|cat)\b/";
foreach ($strings as $str) {
preg_match_all($pattern, $str, $matches);
print_r($matches[0]);
}
输出
Array
(
[0] => cat
)
Array
(
[0] => dog cat dog
)
Array
(
)
Array
(
[0] => cat
)
Array
(
[0] => cat
[1] => cat
[2] => dog cat dog
[3] => cat
)
另一种使用捕获组的方法是匹配您想要避免的内容,并捕获您想要保留的内容。对于匹配的空格,可以使用\s,但请注意,它也可以匹配换行符
\bdog cat\b(?! dog\b)|\b(dog cat dog|cat)\b
如果一个量词在lookback断言中可用,您也可以使用
\bdog cat dog\b|(?<!dog *)\bcat\b|cat(?= *dog\b)
在使用捕获组时,您将获得2个匹配项 使用您尝试的模式dog\s*?cat\s*?1dog,您可以得到一个猫对狗猫的匹配 这是因为模式可以选择性地匹配狗。若有狗,它会被抓获,然后尝试匹配猫 然后在if子句中声明:如果我们有第1组,则匹配狗。发生的情况是,如果组1中没有匹配项,它仍然可以匹配cat,因为捕获组1是可选的 因此,在“狗-猫”中,它最终无法与“狗”匹配,但当尝试从“猫”开始时,它可以与后面的“猫”匹配 如果你想匹配所有3个单词“狗-猫-狗”或只匹配一只猫,而你不想匹配“狗-猫”,你可以使用
\b(?:dog cat dog|dog cat\b(*SKIP)(*F)|cat)\b
\b防止部分匹配的单词边界
?:非捕获组
狗猫狗狗比赛
|或
狗猫\b*跳过*F如果狗猫跳过比赛
|或
猫只会数学
关闭非捕获组
\b单词边界
|
比如说
$strings = [
"cat",
"dog cat dog",
"dog cat",
"cat dog",
"this cat cat is a test dog cat dog cat"
];
$pattern = "/\b(?:dog cat dog|dog cat\b(*SKIP)(*F)|cat)\b/";
foreach ($strings as $str) {
preg_match_all($pattern, $str, $matches);
print_r($matches[0]);
}
输出
Array
(
[0] => cat
)
Array
(
[0] => dog cat dog
)
Array
(
)
Array
(
[0] => cat
)
Array
(
[0] => cat
[1] => cat
[2] => dog cat dog
[3] => cat
)
另一种使用捕获组的方法是匹配您想要避免的内容,并捕获您想要保留的内容。对于匹配的空格,可以使用\s,但请注意,它也可以匹配换行符
\bdog cat\b(?! dog\b)|\b(dog cat dog|cat)\b
如果一个量词在lookback断言中可用,您也可以使用
\bdog cat dog\b|(?<!dog *)\bcat\b|cat(?= *dog\b)
但是,如果单词cat前面有单词dog,那么cat后面还必须有dog,并且所有3个单词都必须匹配
根据我的解释,此正则表达式可能也适用于您:
\b:狗猫狗?
正则表达式详细信息:
\b:词界
?::启动非捕获组
狗猫狗:匹配狗猫狗
|:
?:如果前面没有单词dog和空格,则匹配cat
:结束非捕获组
\b:词界
但是,如果单词cat前面有单词dog,那么cat后面还必须有dog,并且所有3个单词都必须匹配
根据我的解释,此正则表达式可能也适用于您:
\b:狗猫狗?
正则表达式详细信息:
\b:词界
?::启动非捕获组
狗猫狗:匹配狗猫狗
|:
?:如果前面没有单词dog和空格,则匹配cat
:结束非捕获组
\b:词界
这是一个例子
它匹配狗和猫,但不匹配狗和猫
我无法在这里发布正则表达式,因为SO声称它没有正确缩进,尽管它是。请检查正则表达式的链接。这里有一个
它匹配狗和猫,但不匹配狗和猫
我无法在这里发布正则表达式,因为SO声称它没有正确缩进
是的。请检查正则表达式的链接。你是说像这样吗\你是说像这样吗\是的,你的正则表达式是有效的。我只是想知道为什么我用的正则表达式没有。当反向参考条件声明它不应该匹配时,它匹配了dog-cat。@ssten即使使用您尝试的模式dDog\s*?cat\s*?1dog,您也会得到一个猫中猫的匹配,这是因为如果有狗它尝试匹配cat,则该模式会选择性地匹配狗。然后在if子句中声明:如果我们有第1组,则匹配狗。发生的情况是,如果组1中没有狗,它仍然可以匹配猫,因为捕获组1是可选的。因此,在《狗猫》中,它最终无法与《狗》相匹敌,但下一只猫在尝试以《猫》开始时,它可以与之匹敌。@anubhava我认为是这样,我还在regex演示中添加了一个这样的示例,以匹配猫狗猫狗中的最后一只猫,这样猫狗猫具有优先权。@anubhava我认为它将匹配该猫,就像第一个要求一样,如果字符串包含单词cat,cat必须匹配。你可以随时发布答案,我是你出色解决方案的粉丝:-@Thefourthbird,是的,我看到了。你说得对。是的,你的正则表达式有效。我只是想知道为什么我用的正则表达式没有。当反向参考条件声明它不应该匹配时,它匹配了dog-cat。@ssten即使使用您尝试的模式dDog\s*?cat\s*?1dog,您也会得到一个猫中猫的匹配,这是因为如果有狗它尝试匹配cat,则该模式会选择性地匹配狗。然后在if子句中声明:如果我们有第1组,则匹配狗。发生的情况是,如果组1中没有狗,它仍然可以匹配猫,因为捕获组1是可选的。因此,在《狗猫》中,它最终无法与《狗》相匹敌,但下一只猫在尝试以《猫》开始时,它可以与之匹敌。@anubhava我认为是这样,我还在regex演示中添加了一个这样的示例,以匹配猫狗猫狗中的最后一只猫,这样猫狗猫具有优先权。@anubhava我认为它将匹配该猫,就像第一个要求一样,如果字符串包含单词cat,cat必须匹配。你可以随时发布答案,我是你出色解决方案的粉丝:-@Thefourthbird,是的,我看到了。你是对的。永远是一件愉快的事+++@anubhava,你为dog-cat-dog@anubhava提供的解决方案,请尝试我已经在我的评论中发布的repl链接。你正在使用\b?=dog-cat-dog |?在你的演示中,这和我的回答不一样。@anubhava,我已经用你的回答试过了。它工作正常。始终是一个愉快的+++@anubhava,您的狗猫狗@anubhava解决方案,请尝试我在评论中已经发布的repl链接。您使用的是\b?=狗猫狗|?在你的演示中,这和我的回答不一样。@anubhava,我已经用你的回答试过了。它工作正常。