简体   繁体   English

用php将正则表达式匹配多个完整单词

[英]Match multiple whole words with regex with php

I'm implementing a "Tags" feature in our custom product management system. 我正在自定义产品管理系统中实现“标签”功能。 Each product has a comma seperated list of tags associated. 每个产品都有一个逗号分隔的关联标签列表。 We have a "tag search" with check boxes. 我们有一个带有复选框的“标签搜索”。 The user can check multiple tags and it will filter with ajax with all the selected tags, so all tags need to be matched together. 用户可以检查多个标签,它将使用所有选定标签的ajax进行过滤,因此所有标签都需要匹配在一起。 Example. 例。

Tags: Tag1,Tag2,Tag3

#1-product-tags: Tag3,Tag10,Tag2
#2-product-tags: Tag1,Tag3,Tag10
#3-product-tags: Tag5,Tag1,Tag3
#4-product-tags: Tag8,Tag4,Tag20
#5-product-tags: Tag20,Tag100,Tag500

When filtering with the above tags checked, I expect to return #1,#2,#3 only because the given tags are listed in the product-tags column of these products. 在选中上述标签的情况下进行过滤时,我希望仅返回#1,#2,#3,因为给定的标签已列在这些产品的产品标签列中。

Im currently trying to use regular expressions by dynamically creating a regex when the user checks the tags. 我目前正在尝试通过在用户检查标签时动态创建正则表达式来使用正则表达式。 In order to qualify as a match, the product must have all tags checked. 为了符合匹配条件,产品必须检查所有标签。 Im generating this like so: 我生成这样的:

   <?php 
       //empty collection array to fill with product loop
       $collection = array();

       //dynamically generated regex
       $regex = "\b" . $tag1 . "|" . $tag2 . "|" . $tag3 . "\b/i";

       //loop through each product and throw matches to collection
       foreach($products as $product) {
         if(preg_match($regex,$product->tags)) {
            array_push($collection,$product);
         }
       }
    ?>

I am not getting the expected result doing it this way. 我这样做没有得到预期的结果。 What is the best way I can get my expected result. 我能得到预期结果的最好方法是什么。 Im not too great with Regular Expressions but I am learning. 我对正则表达式不太满意,但我正在学习。

I'm assuming the tags are stored in an array as comma-separated strings. 我假设标签以逗号分隔的字符串形式存储在数组中。 If that's the case, you can split them into individual arrays using explode() and then loop through the array and use array_intersect() to see if any of the sub-arrays have all the values in the $search array: 如果是这种情况,您可以使用explode()将它们分成单个数组,然后遍历该数组并使用array_intersect()来查看是否有任何子数组具有$search数组中的所有值:

$search = ['Tag1', 'Tag2', 'Tag3'];

$taglist = array_map(function ($v) { return explode(',', $v); }, $tags);

foreach ($taglist as $sub) {
    if (count(array_intersect($sub, $search)) == count($search)) {
        $products[] = implode(',', $sub);
    }
}

Not only this approach is efficient, it is more flexible. 这种方法不仅有效,而且更加灵活。 It will not be a problem if you have multiple conditions to check for. 如果您有多个条件要检查,这将不是问题。 If you were to do this with a regex, you'd have a hard time crafting the regex and chances are it will be a lot slower than this simple split & loop solution. 如果您要使用正则表达式执行此操作,则将很难制作正则表达式,并且它会比此简单的拆分和循环解决方案慢很多。

For the tags in the question, this would return nothing — $products array would be empty. 对于问题中的标签,这将不返回任何内容- $products数组为空。

Demo 演示版

If you still want to go with the regex i recommand some regex like 如果您仍然想使用正则表达式,我建议您使用一些正则表达式,例如

Tag2(,.*)?$|Tag1(,.*)?$/i

See live example here 在此处查看实时示例

With new specifications you have to use positive lookahead 对于新规格,您必须提前使用正向

(?=(((Tag1|Tag2|Tag3)(,.*)?$)))

See live example here 在此处查看实时示例

I think your regular expression has 2 small details to consider. 我认为您的正则表达式需要考虑2个小细节。 1 - missing the first delimiter character / 2 - group in brackets the options you want to choose one of them 1-缺少第一个定界字符/ 2-放在括号中的组您要选择的选项之一

$regex = "/\b(" . $tag1 . "|" . $tag2 . "|" . $tag3 . ")\b/i";


try with this code to see my result.
<?php
 $tag1 = 'Tag1';
 $tag2 = 'Tag2';
 $tag3 = 'Tag3';

$arr = array();
$arr["#1-product-tags"] = "Tag3,Tag10,Tag2";
$arr["#2-product-tags"] = "Tag1,Tag3,Tag10";
$arr["#3-product-tags"] = "Tag5,Tag1,Tag3";
$arr["#4-product-tags"] = "Tag8,Tag4,Tag20";
$arr["#5-product-tags"] = "Tag20,Tag100,Tag500";
var_dump($arr);

//empty collection array to fill with product loop
$collection = array();

//dynamically generated regex
$regex = "/\b(" . $tag1 . "|" . $tag2 . "|" . $tag3 . ")\b/i";
var_dump($regex);

//loop through each product and throw matches to collection
foreach($arr as $product) {
    //var_dump($product);
    if(preg_match($regex,$product)) {
        array_push($collection,$product);
    }
}
var_dump($collection);
?>

Ive finally came up with a solution that worked. Ive最终提出了一个可行的解决方案。 /^(?=.*?Tag1)(?=.*?Tag2)(?=.*?Tag3).*$/ works like a charm /^(?=.*?Tag1)(?=.*?Tag2)(?=.*?Tag3).*$/就像一个护身符

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM