我有以下正则表达式代码
$str = 'word1 word2 word3 keyword word4 word5 word6 keyword word7 word8 word9 word10';
$matches = array();
preg_match_all('/(\w* ){1,3}keyword( \w*){1,3}/u', $str, $matches);
我希望比赛包括:
word1 word2 word3关键字word4 word5 word6
word4 word5 word6关键字word7 word8 word9
但实际上,我得到的是:
word1 word2 word3关键字word4 word5 word6
关键字word7 word8 word9
换句话说,第二场比赛因第一场比赛而被裁切。
这是一个测试:https://regex101.com/r/EPp14b/1/
您需要的整个部分(周围的关键字)都在前瞻性断言中的捕获组(结果)中,这样字符就不会被使用,并且可以在以后的最终下一个匹配中使用。但是为了避免多次匹配同一个关键字,您需要到达该关键字之后的位置,并使用所有字符,直到包含该关键字为止。这就是为什么我定义了一个名为consume的组,并引用了他的内容:\g{consume}
。
$pattern = '~
\b
(?=
(?<result>
(?<consume>
(?> \w+ \h+ ){0,3}?
keyword \b
)
(?: \h+ (?! keyword \b ) \w+ ){0,3}
)
) \g{consume}
~ux';
演示
使用此模式,您不必重新构建结果,所有结果都存储在命名的组结果中:
preg_match_all($pattern, $str, $matches);
print_r($matches['result']);
如果您不想跨越关键字,可以在重复1-3个单词时使用否定的前瞻性来断言它们不是关键字。
匹配后,您可以对捕获组使用积极的前瞻性断言,匹配1-3个不是关键字的单词
这句话将是完全匹配和组1的串联。
(?<!\S)(?:(?!keyword\b)\w+\h+){1,3}keyword\b(?=((?:\h+(?!keyword\b)\w+){1,3}))
模式匹配:
(
捕获组1
(?:\h(?! keyword\b)\w){1,3}
匹配1-3个不以keyword
开头的词正则表达式演示|Php演示
$re = '/(?<!\S)((?:(?!keyword\b)\w+\h+){1,3}keyword\b)(?=((?:\h+(?!keyword\b)\w+){1,3}))/u';
$strings = [
"word1 word2 word3 keyword word4 word5 word6 keyword word7 word8 word9 word10",
"word2 keyword word4 word5 word6 keyword word7 word8",
"word2 word3 keyword word4 word5 word6 keyword word7 keyword word10",
];
foreach ($strings as $str) {
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
$matches = array_map(function($m) {
return $m[1] . $m[2];
}, $matches);
print_r($matches);
}
输出
Array
(
[0] => word1 word2 word3 keyword word4 word5 word6
[1] => word4 word5 word6 keyword word7 word8 word9
)
Array
(
[0] => word2 keyword word4 word5 word6
[1] => word4 word5 word6 keyword word7 word8
)
Array
(
[0] => word2 word3 keyword word4 word5 word6
[1] => word4 word5 word6 keyword word7
[2] => word7 keyword word10
)
另一种选择是将完整匹配放在前瞻内的捕获组中,以便能够获得重叠匹配:
(?=((\b(?:\w+\h+){1,3}keyword)(?:\h+\w+){1,3}))(?2)
RegEx演示
代码:
$s = 'word1 word2 word3 keyword word4 word5 word6 keyword word7 word8 word9 word10';
$re = '/(?=((\b(?:\w+\h+){1,3}keyword)(?:\h+\w+){1,3}))(?2)/u';
preg_match_all($re, $s, $m);
print_r($m[1]);
/* Output
Array
(
[0] => word1 word2 word3 keyword word4 word5 word6
[1] => word4 word5 word6 keyword word7 word8 word9
)
*/
正则表达式详细信息:
(? =
:开始前瞻
(
:开始捕获组#1
(
:开始捕获组#2
\b
:单词边界(?:\w\h){1,3}
:匹配1到3个单词关键字
:我是不是漏掉了什么?提前感谢!
问题内容: 我想在查询上使用模糊匹配,但在结果顶部显示完全匹配。 我已经尝试了以下方法。 由于格式错误的查询错误,此方法不起作用。 有任何想法吗? 问题答案: 我最终没有使用模糊匹配来解决我的问题,而是使用了ngram。 结果正是我想要的。它根据搜索查询中包含的ngram部分构造匹配项。
在PostgreSQL中获得最长前缀匹配的准确快速查询的最佳方法是什么? 是: 我计划在更新中使用。有什么想法吗?
我在列表中有这样的数据: 我当前的解决方案能够检测到完全匹配的重复项。因此,它当前将输出: 我想增加一些可能性,以便它们也在输出列表中: 下面是我当前的代码: 我将非常感谢任何善意的建议,以导致实现这种检查的解决办法?我个人认为这里没有任何可能的合乎逻辑的解决办法?也许只是某种基于分数的Levenshtein距离计算和检测?如果这是不可能的,将是有益的,至少得到这些(匹配多个单词,例如两个):
我正在尝试执行一个bash文件,该文件执行以下操作: 从文件夹中,仅提取文件名中包含干净单词的文件夹。 从这些中,如果其中有一个1,那么取那个和下面的。 现在,我站在这一点上: 我对if语句有问题,因为我不知道如何表达它 谢谢
foo-bar-herp foo-bar-derp baz-blub其他东西 我想提供一个搜索工作,以便 “foo bar”(标记化前缀) “Foo Herp”(跳过令牌) “foo-bar-”(确切的前缀) “bar-herp”(中间的确切字符串) “foo ba”(一个完整的令牌和另一个令牌的前缀) null