在找到不同的特定词后计算特定词的出现次数
Count occurrences of specific word after a different, specific word is found
我对正则表达式还比较陌生,并且一直停留在以下我尝试使用 preg_match_all
到 count the number of hello after world 的地方。
如果我用"world".+(hello)
,算到最后hello; "world".*?(hello)
停在第一个 hello,两者都算一个。
blah blah blah
hello
blah blah blah
class="world"
blah blah blah
hello
blah blah
hello
blah blah blah
hello
blah blah blah
我期待 3
作为计数,因为 world
之前的 hello
不应该被计数。
一种方法可能是首先去除字符串的前导部分,直到并包括第一次出现的 world
。然后像您已经在做的那样调用 preg_match_all
并获取 hello
.
的出现次数
$input = "blah blah blah
hello
blah blah blah
class=\"world\"
blah blah blah
hello
blah blah
hello
blah blah blah
hello
blah blah blah";
$input = preg_replace("/^.*?\bworld/", "", $input);
preg_match_all("/\bhello\b/", $input, $matches);
echo sizeof($matches[0]); // 4
您可以在此处使用单个 preg_match_all
调用:
$text = "blah blah blah\nhello\nblah blah blah\nclass=\"world\" \nblah blah blah\nhello \nblah blah\nhello\nblah blah blah\nhello\nblah blah blah";
echo preg_match_all('~(?:\G(?!^)|\bworld\b).*?\K\bhello\b~s', $text);
见regex demo and the PHP demo。 详情:
(?:\G(?!^)|\bworld\b)
- 上一场比赛的结束(\G(?!^)
做这个检查:\G
matches either start of the string or end of the previous match position,所以我们需要排除字符串位置的开始,这是通过 (?!^)
负前瞻)或整个单词 world
.*?
- 任意零个或多个字符,尽可能少
\K
- 丢弃目前匹配的所有文本
\bhello\b
- 一个完整的单词 hello
.
注意:如果不需要单词边界检查,可以从模式中删除\b
。
如果hello
和world
是用户定义的模式,你必须preg_quote
他们在模式中:
$start = "world";
$find = "hello";
$text = "blah blah blah\nhello\nblah blah blah\nclass=\"world\" \nblah blah blah\nhello \nblah blah\nhello\nblah blah blah\nhello\nblah blah blah";
echo preg_match_all('~(?:\G(?!^)|' . preg_quote($start, '~') . '\b).*?\K' . preg_quote($find, '~') . '~s', $text);
另一个带有简单正则表达式的选项:
if(preg_match('/"world".*/s', $str, $out)) {
echo preg_match_all('/\bhello\b/', $out[0]);
}
其他方式:如果字符串中不存在 world
,则强制模式失败并且不重试:
~(?:\A(*COMMIT).*?world)?.*?hello~s
非捕获组是可选的但贪婪的。结果,每次尝试模式时都会对其进行测试。
它以匹配字符串开头的 \A
锚点开始,因此这是该组唯一可以成功的位置。在字符串开始之后,在其他位置 \A
失败并且由于该组是可选的,因此忽略其中剩余的子模式并继续研究 .*?hello
.
紧随其后的是回溯控制动词 (*COMMIT)
,万一在它之后失败,则强制根本不重试该模式。 (故事结束)。
换句话说,如果该组在字符串的开头失败,则研究将永远中止。
优点:与基于 \G
的模式相比,它需要的步骤更少。
为了提高效率,基于 \G
的模式也可以这样写(使用可选组而不是交替):
~(?:\A.*?world)?(?!\A).*?hello~sA
这里的修饰符 A 起到了 \G
锚点的作用,但它与用 \G
锚点开始一个模式的每个分支(这里只有一个)完全一样。
我对正则表达式还比较陌生,并且一直停留在以下我尝试使用 preg_match_all
到 count the number of hello after world 的地方。
如果我用"world".+(hello)
,算到最后hello; "world".*?(hello)
停在第一个 hello,两者都算一个。
blah blah blah
hello
blah blah blah
class="world"
blah blah blah
hello
blah blah
hello
blah blah blah
hello
blah blah blah
我期待 3
作为计数,因为 world
之前的 hello
不应该被计数。
一种方法可能是首先去除字符串的前导部分,直到并包括第一次出现的 world
。然后像您已经在做的那样调用 preg_match_all
并获取 hello
.
$input = "blah blah blah
hello
blah blah blah
class=\"world\"
blah blah blah
hello
blah blah
hello
blah blah blah
hello
blah blah blah";
$input = preg_replace("/^.*?\bworld/", "", $input);
preg_match_all("/\bhello\b/", $input, $matches);
echo sizeof($matches[0]); // 4
您可以在此处使用单个 preg_match_all
调用:
$text = "blah blah blah\nhello\nblah blah blah\nclass=\"world\" \nblah blah blah\nhello \nblah blah\nhello\nblah blah blah\nhello\nblah blah blah";
echo preg_match_all('~(?:\G(?!^)|\bworld\b).*?\K\bhello\b~s', $text);
见regex demo and the PHP demo。 详情:
(?:\G(?!^)|\bworld\b)
- 上一场比赛的结束(\G(?!^)
做这个检查:\G
matches either start of the string or end of the previous match position,所以我们需要排除字符串位置的开始,这是通过(?!^)
负前瞻)或整个单词world
.*?
- 任意零个或多个字符,尽可能少\K
- 丢弃目前匹配的所有文本\bhello\b
- 一个完整的单词hello
.
注意:如果不需要单词边界检查,可以从模式中删除\b
。
如果hello
和world
是用户定义的模式,你必须preg_quote
他们在模式中:
$start = "world";
$find = "hello";
$text = "blah blah blah\nhello\nblah blah blah\nclass=\"world\" \nblah blah blah\nhello \nblah blah\nhello\nblah blah blah\nhello\nblah blah blah";
echo preg_match_all('~(?:\G(?!^)|' . preg_quote($start, '~') . '\b).*?\K' . preg_quote($find, '~') . '~s', $text);
另一个带有简单正则表达式的选项:
if(preg_match('/"world".*/s', $str, $out)) {
echo preg_match_all('/\bhello\b/', $out[0]);
}
其他方式:如果字符串中不存在 world
,则强制模式失败并且不重试:
~(?:\A(*COMMIT).*?world)?.*?hello~s
非捕获组是可选的但贪婪的。结果,每次尝试模式时都会对其进行测试。
它以匹配字符串开头的 \A
锚点开始,因此这是该组唯一可以成功的位置。在字符串开始之后,在其他位置 \A
失败并且由于该组是可选的,因此忽略其中剩余的子模式并继续研究 .*?hello
.
紧随其后的是回溯控制动词 (*COMMIT)
,万一在它之后失败,则强制根本不重试该模式。 (故事结束)。
换句话说,如果该组在字符串的开头失败,则研究将永远中止。
优点:与基于 \G
的模式相比,它需要的步骤更少。
为了提高效率,基于 \G
的模式也可以这样写(使用可选组而不是交替):
~(?:\A.*?world)?(?!\A).*?hello~sA
这里的修饰符 A 起到了 \G
锚点的作用,但它与用 \G
锚点开始一个模式的每个分支(这里只有一个)完全一样。