簡體   English   中英

php正則表達式在子字符串中查找子字符串

[英]php regex find substring in substring

我仍然在玩一個帶有匹配詞的項目。

假設我有一個給定的字符串,比如maxmuster 然后我想記住我的隨機字MAXS這是在maxmuster按正確的順序,如字母的這一部分。

我會舉一些例子,然后我會告訴我我已經做了什么。 讓我們保留字符串maxmuster 粗體部分是正則表達式匹配的部分(最好是在 php 中,但也可能是 python、bash、javascript 等)

最大

我的maxmu

鼓起

當然, m , u , ... 也會匹配。 我知道,我稍后會解決這個問題。 但是,我認為解決方案應該不那么困難,所以我嘗試將這個詞分成這樣的組:

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

但是后來我當然忘記了其他組合,例如:

(axmuster)(xmus)等等。 我真的必須這樣做,還是存在一個簡單的正則表達式技巧來解決這個問題,就像我上面解釋的那樣?

非常感謝

聽起來你需要字符串交集。 如果您不介意非正則表達式的想法,請查看 Wikibooks Algorithm Implementation/Strings/Longest common substring PHP 部分。

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

最大限度
最大畝

鼓起

在 tio.run 上查看這個 PHP 演示(無案例比較)。


如果你需要一個正則表達式的想法,我會用空格連接兩個字符串並使用像這個演示這樣的模式。

(?=(\w+)(?=\w* \w*?\1))\w

它將在第一個字符串中的單詞字符之前的每個位置的前瞻捕獲也與第二個字符串匹配的最長子字符串。 然后通過 PHP 匹配第一組需要按長度排序,並返回最長的匹配。 請參閱tio.run 上PHP 演示

function get_longest_common_subsequence($w1="", $w2="")
{
  $test_str = preg_quote($w1,'/')." ".preg_quote($w2,'/');

  if(preg_match_all('/(?=(\w+)(?=\w* \w*?\1))\w/i', $test_str, $out) > 0)
  {
    usort($out[1], function($a, $b) { return strlen($b) - strlen($a); });
    return $out[1][0];
  }
}

TL; 博士

使用正則表達式:

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

完整片段


使用下面的正則表達式,您可以匹配字符串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]))

現場演示

您必須從maxmuster之類的單詞中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 現場演示

這是我使用正則表達式解決這個問題的看法。

<?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 演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM