用于获取仅包含模式列表中单词的字符串的正则表达式?

Posted

技术标签:

【中文标题】用于获取仅包含模式列表中单词的字符串的正则表达式?【英文标题】:Regex for getting strings that contains only the words from the pattern list? 【发布时间】:2019-03-10 04:09:43 【问题描述】:

考虑以下数组元素

 1.benclinton
 2.clintonharry
 3.harryben
 4.benwill
 5.jasonsmith
 6.smithclinton

假设模式列表是ben,harry,clinton,那么我应该得到的结果是

1.benclinton  
2.clintonharry  
3.harryben

因此,基本上结果应该包含仅包含模式列表中的单词的字符串。顺序不重要

此外,每个字符串不会超过两个单词。也就是说,本史密斯永远不会成为案例。

由于我所有的字符串都在一个数组中,我想在 php 中使用 preg_grep 来执行此操作,但我对为此构建正确的正则表达式感到震惊。

什么正则表达式可以做到这一点?除了正则表达式匹配之外,还有其他有效的方法可以完成这项工作吗?

提前致谢!

【问题讨论】:

【参考方案1】:

类似的东西

$names_list = ['benclinton','clintonharry','harryben','benwill','jasonsmith','smithclinton'];
$names = ['ben','harry','clinton'];  

$matches = preg_grep('/('.implode('|',$names).')(?1)/', $names_list);
//-  /(ben|harry|clinton)(?1)/  -- (?1) = recurse capture group 1 

print_r($matches);

输出

Array
(
    [0] => benclinton
    [1] => clintonharry
    [2] => harryben
)

Sandbox

这要求至少有两个名称(即使是同一个 2x)匹配。但在这种情况下,这是给定的,否则一切都会匹配。

如果你想格外小心,如果$names 可以包含一些对正则表达式很重要的东西,例如+*\ 等,你可以添加这个

$matches = preg_grep('/('.implode('|',array_map(function($name)return preg_quote($name,'/');,$names)).')(?1)/', $names_list);

【讨论】:

这匹配benbenclinton。不确定 OP 是否期望一个术语与两个子字符串完全匹配。 @TimBiegeleisen - 你的也是。 Sandbox 我可以用 ^$ Sandbox 做同样的事情 - 只是说。 :-)【参考方案2】:

您似乎想要匹配两个关键字的精确组合的数组元素。对于正则表达式方法,我们可以尝试取 keyords 向量的叉积,然后生成一个交替。然后,我们可以对您的输入数组使用preg_grep 来查找所有匹配的元素。

$array = array("benclinton", "clintonharry", "harryben", "benwill", "jasonsmith", "smithclinton");
$input = array("ben", "harry", "clinton");
$regex = "";
foreach ($input as $term1)  
    foreach ($input as $term2)  
        if ($regex != "") $regex .= "|";
        $regex .= $term1.$term2;
    

$regex = "/^(" . $regex . ")$/";
$matches = preg_grep($regex, $array);
print_r($matches);

Array
(
    [0] => benclinton
    [1] => clintonharry
    [2] => harryben
)

这是上面脚本生成的正则表达式交替:

(benben|benharry|benclinton|harryben|harryharry|harryclinton|clintonben|
    clintonharry|clintonclinton)

【讨论】:

谢谢。有什么办法不用for循环?【参考方案3】:

不使用 Regex.Do with array_filterstrpos

    过滤器数组与计数大于 1 的第二个数组匹配

Sandbox

<?php
$a = ['benclinton','clintonharry','harryben','benwill','jasonsmith','smithclinton'];
$a2 = ['ben','clinton','harry'];
$res = array_filter($a,function($str="") use($a2)
    $r =array_filter($a2,function($a2str) use($str)
        return strpos($str,$a2str) !== FALSE;
    );
    return count($r) > 1;
);
print_r($res);
?>

【讨论】:

以上是关于用于获取仅包含模式列表中单词的字符串的正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章

用于匹配单词的 javascript 正则表达式模式,具有自定义单词边界

正则表达式检查句子中仅包含字母的两个单词

用于检查字符串是不是不应包含某些单词的正则表达式,但如果这些单词前面有“to”或“for”,则这些单词是可以的

用于单词列表的正则表达式过滤器,直到第 n 次出现字符

在字符串列表中查找特定模式(正则表达式)(Python)

不包含多个特定单词的字符串的正则表达式