php regex在子字符串中查找子字符串

时间:2017-04-27 18:39:18

标签: php regex

我还在玩一个有匹配词的项目。

假设我有一个给定的字符串,比如 maxmuster 。然后我想在 maxmuster 中标记随机字 maxs 部分>按照正确的顺序,就像字母一样。

我会举一些例子然后告诉我已经做过的事情。让我们保持字符串 maxmuster 。粗体部分是由正则表达式匹配的(最好是在php中,但可能是python,bash,javascript,...)

最大取值

我的 maxmu

勒的

鼓起

当然 m ,......也会匹配。我知道,我稍后会解决这个问题。但是,我的解决方案应该不会那么困难,所以我尝试将这个词分成这样的组:

/(maxmuster)?|(maxmuste)?|(maxmust)?|(maxmus)?|(maxmu)?|(maxm)?|(max)?|(ma)?|(m)?/gui

但后来我忘了其他组合,比如:

(axmuster)(xmus)等等。我是否真的必须这样做,或者存在一个简单的正则表达技巧来解决这个问题,就像我上面解释过的那样?

非常感谢

3 个答案:

答案 0 :(得分:2)

听起来你需要字符串交集。如果您不介意非正则表达式的想法,请查看Wikibooks Algorithm Implementation/Strings/Longest common substring PHP部分。

foreach(["maxs", "Mymaxmuis", "Lemu", "muster"] AS $str)
  echo get_longest_common_subsequence($str, "maxmuster") . "\n";
  

最大
  maxmu
  亩
  鼓起

See this demo at eval.in(无壳比较)。

答案 1 :(得分:1)

TL; DR

使用正则表达式:

longestSubstring(['Mymaxmuis', 'axmuis', 'muster'], buildRegexFrom('maxmuster'));

Full snippet

使用下面的正则表达式,您可以匹配字符串maxmuster的所有真实子字符串:

(?|((?:
    m(?=a)
    |(?<=m)a
    |a(?=x)
    |(?<=a)x
    |x(?=m)
    |(?<=x)m
    |m(?=u)
    |(?<=m)u
    |u(?=s)
    |(?<=u)s
    |s(?=t)
    |(?<=s)t
    |t(?=e)
    |(?<=t)e
    |e(?=r)
    |(?<=e)r
)+)|([maxmuster]))

<强> Live demo

你必须从像maxmuster这样的单词中制作这样的正则表达式,所以你需要一个函数来调用它:

function buildRegexFrom(string $word): string {
    // Split word to letters
    $letters = str_split($word);
    // Creating all side of alternations in our regex
    foreach ($letters as $key => $letter)
        if (end($letters) != $letter)
            $regex[] = "$letter(?={$letters[$key + 1]})|(?<=$letter){$letters[$key + 1]}";
    // Return whole cooked pattern
    return "~(?|((?>".implode('|', $regex).")+)|([$word]))~i";
}

要返回最长匹配,您需要根据从最长到最短的匹配长度对结果进行排序。这意味着为它编写另一段代码:

function longestSubstring(array $array, string $regex): array {
    foreach ($array as $value) {
        preg_match_all($regex, $value, $matches);
        usort($matches[1], function($a, $b) {
            return strlen($b) <=> strlen($a);
        });
        // Store longest match being sorted
        $substrings[] = $matches[1][0];
    }

    return $substrings;
}

把所有事情放在一起:

print_r(longestSubstring(['Mymaxmuis', 'axmuis', 'muster'], buildRegexFrom('maxmuster')));

输出:

Array
(
    [0] => maxmu
    [1] => axmu
    [2] => muster
)

<强> PHP live demo

答案 2 :(得分:0)

以下是我使用正则表达式解决此问题的方法。

<?php
$subject="maxmuster";
$str="Lemu";

$comb=str_split($subject); // Split into single characters.
$len=strlen($subject);

for ($i=2; $i<=$len; $i++){
    for($start=0; $start<$len; $start++){
        $temp="";
        $inc=$start;
        for($j=0; $j<$i; $j++){
            $temp=$temp.$subject[$inc];
            $inc++;
        }
        array_push($comb,$temp);
    }
}

echo "Matches are:\n";
for($i=0; $i<sizeof($comb); $i++){
    $pattern = "/".$comb[$i]."/";
    if(preg_match($pattern,$str, $matches)){
        print_r($matches);  
    };
}
?>

这是 Ideone Demo