preg_replace_callback高亮模式在结果中不匹配

时间:2014-01-22 02:16:34

标签: php regex algorithm replace

我有这段代码:

$string = 'The quick brown fox jumped over the lazy dog and lived to tell about it to his crazy moped.';
$text = explode("#", str_replace(" ", " #", $string)); //ugly trick to preserve space when exploding, but it works (faster than preg_split)
foreach ($text as $value) {
    echo preg_replace_callback("/(.*p.*e.*d.*|.*a.*y.*)/", function ($matches) {
        return " <strong>".$matches[0]."</strong> ";
    }, $value);
}

要点是能够输入一系列字符(在上面的代码中是一个固定的模式),它会找到并突出显示匹配单词中的那些字符。我现在的代码突出了整个单词。我正在寻找突出角色的最有效方式。 当前代码的结果:

  

快速的棕色狐狸跳过 lazy 狗,然后活着告诉他的疯狂 轻便摩托车。

我想拥有什么:

  

快速的棕色狐狸jum ped 超过了 a z y 狗并活着告诉他的cr a z y mo ped

我采取了错误的做法吗?如果有人能以正确的方式指出我,那将是非常棒的,我一直在寻找几个小时但没有找到我想要的东西。

编辑2: 迪瓦卡是一个很好的帮助。几乎就在那里......如果我对目标不明确,我会道歉。我会尝试进一步解释。

- A部分 -

我将使用此代码的其中一项是电话簿。一个简单的例子: 输入以下字符时:

  

我需要它来匹配以下示例:

  

Jan Verhoeven
  Ar jan 彼得斯   Ra j N a 重新 n
   J ered Von Tr an

问题在于我将遍历整个电话簿,每人记录的人事记录。每个人还有电子邮件地址,邮政地址,可能是网站,额外的注释等。这意味着我实际搜索的文本可以包含letters, numbers, special characters(&@()%_- etc..), newlines, and most importantly spaces中的任何内容。因此整个记录(csv)可能包含以下信息:

  

姓名;地址;电子邮件地址;网站;注​​意

  Jan Verhoeven; Veldstraat 2a,3209 Herkstad; jan@werk.be; www.janophetwerk.be,jan @ telemet.be; Jan die ik ontmoet heb op de bouwbeurs。\ n Zelfstandige vertegenwoordiger van bouwmaterialen。

  Raj Naren; Kerklaan 334,5873 Biep; raj@werk.be ;; Rechtstreekse contactpersoon bij Werk.be(#654实习生)

\n是一个真正的换行符。因此,如果我搜索@werk.be,我希望将这两个记录视为结果。

- B部分 -

我想用它来做的其他事情就是搜索歌曲文本。当我正在寻找一首歌时,我只能记住它必须用鸭子或码头和圆圈做一些事情,我会输入dckcircle并获得以下结果:

  

... d ck s都在一个伟大的中跳舞,围绕着巨大的篝火......

为了能够微调搜索,我希望能够限制空格(或任何其他角色)的数量,因为我会想象它会在每首歌中找到像eve这样的简单模式虽然我只是在寻找一首其中包含eve字样的歌曲。

- 结论 -

如果我在伪正则表达式中总结一下,对于中间最多有3个空格的搜索模式abc,它将是这样的:(我可能完全不在这里)

  

(a)(任何字符,最多3个空格)(b)(任何字符,最多3个空格)(c)

或更通用:

  

(a)({任何字符} {这些字符的限制为3}}(b)({任何字符} {这些字符的限制为3})(c)

我猜这个甚至可以很容易地扩展到这个:

  

(a)({任何字符} {这些字符的限制为3} {不是这些字符})(b)({任何字符} {这些字符的限制为3} {不是这些字符})( c)中

(我知道'{}'括号不能在正则表达式中以这种方式使用,但我不知道如何在不使用正则表达式中有意义的字符的情况下放置它。 )

<小时/> 如果有人想知道,我知道sql like语句可以做80%(我猜,甚至可能更多)我正在尝试做的事情,但我试图避免使用使数据库尽可能便携的数据库 当找到正确的答案时,我会清理这个问题(和代码),然后在这里发布得到的php类(也许我甚至会把它放在github上,如果那样会有用),所以任何人都在寻找同样会有一个完全可以工作的班级:)。

1 个答案:

答案 0 :(得分:0)

我想出了这个。告诉我这是不是你想要的!

//$string = "The quick brown fox jumped over the lazy dog and lived to tell about it to his crazy moped.";
$string = "abcdefo";

//$pattern_array1 = array(a,y);
//$pattern_array2 = array(p,e,d);
$pattern_array1 = array(e,f);
$pattern_array2 = array(o);
$pattern_array2 = array(a,f);

$number_of_patterns = 2;

$regexp1 = generate_regexp($pattern_array1, 1);
$regexp2 = generate_regexp($pattern_array2, 2);

$string = preg_replace($regexp1["pattern"], $regexp1["replacement"], $string);
$string = preg_replace($regexp2["pattern"], $regexp2["replacement"], $string);

$string = transform_multimatched_chars($string);

// transforming other chars after transforming the multimatched ones
for($i = 1; $i <= $number_of_patterns; $i++) {
    $string = str_replace("#{$i}", "<strong>", $string);
    $string = str_replace("#/{$i}", "</strong>", $string);
}

echo $string;

function generate_regexp($pattern_array, $pattern_num) {
    $regexp["pattern"] = "/";
    $regexp["replacement"] = "";
    $i = 0;
    foreach($pattern_array as $key => $char) {
        $regexp["pattern"] .= "({$char})";
        $regexp["replacement"] .= "#{$pattern_num}\$". ($key + $i+1) . "#/{$pattern_num}";
        if($key < count($pattern_array) - 1) {
            $regexp["pattern"] .= "(?s)((?:(?!{$pattern_array[$key + 1]})(?!\s).)*)";
            $regexp["replacement"] .= "\$".($key + $i+2) . "";
        }

        $i = $key + 1;
    }
    $regexp["pattern"] .= "/";

    return $regexp;
}

function transform_multimatched_chars($string)
{
    preg_match_all("/((#[0-9]){2,})(.*)((#\/[0-9]){2,})/", $string, $matches);

    // change this for your purposes
    $start_replacement = '<span style="color:red;">';
    $end_replacement = '</span>';

    foreach($matches[1] as $key => $match)
    {
        $string = str_replace($match, $start_replacement, $string);
        $string = str_replace($matches[4][$key], $end_replacement, $string);
    }

    return $string;
}