【问题标题】:preg_replace_callback highlight pattern not match in resultpreg_replace_callback 高亮模式在结果中不匹配
【发布时间】:2014-02-11 22:05:51
【问题描述】:

我有这个代码:

$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);
}

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

敏捷的棕色狐狸跳过懒惰的狗,并活着告诉他的疯狂轻便摩托车。

我想要什么:

快速的棕色狐狸ped跳过lazy狗并活着告诉他的cra zy moped

我是否采取了错误的方法?如果有人能以正确的方式指出我,那就太棒了,我已经搜索了几个小时,但没有找到我想要的东西。

编辑 2: 迪瓦卡帮了大忙。快到了.. 如果我对我的目标不够清楚,我深表歉意。我会尝试进一步解释。

- A 部分 -

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

一月

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

一月韦尔霍文
Arjan彼得斯
Raj Naren
Jered Von Tran

问题是我将遍历整个电话簿,每个人记录的人记录。每个人也有电子邮件地址、邮政地址、可能是网站、额外说明等。这意味着我实际搜索的文本可以包含来自letters, numbers, special characters(&amp;@()%_- 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 并得到以下结果:

...和 ​​duck 们都围着巨大的篝火围着一个很大的圆圈跳舞...

为了能够微调搜索,我希望能够限制空格(或任何其他字符)的数量,因为我可以想象它会在每首歌曲中找到一个简单的模式,例如 eve,而我我只是在寻找一首包含确切单词 eve 的歌曲。

- 结论 -

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

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

或更通用的:

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

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

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

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


如果有人想知道,我知道 sql like 语句将能够完成我正在尝试做的 80%(我猜,甚至可能更多),但我试图避免使用数据库使其尽可能便携。
找到正确答案后,我会清理这个问题(和代码)并将生成的 php-class 发布在这里(如果有用的话,我什至会把它放在 github 上),所以任何人都在寻找同样将有一个完整的工人阶级来工作:)。

【问题讨论】:

  • 你想在'a'和'y'之间有一个字符吗?你来这里的目的是什么?
  • 这取决于你想要什么规则。如果您只想找到“ped”,无论它位于单词中的哪个位置并突出显示它str_replace 都可以解决问题,如果您只想在单词的末尾找到它,您应该玩一点
  • 目的是能够输入一个字符序列,并且在单词中找到它,位置无关,只要它们在那个顺序。一个例子是 sublime text 的自动完成:当你在一个 css 文件中输入“paddr”时,它会提示“padding-right”并在提示中突出显示输入的字符(“paddr”)。这就是我试图用 php 完成的。
  • 你试过我的答案了吗?
  • 刚刚有时间测试它,它看起来不错,看来您对此有所考虑。但是有一个问题,看看我的编辑。

标签: php regex algorithm replace


【解决方案1】:

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

//$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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-19
    • 2022-01-15
    • 2014-07-13
    • 2016-02-08
    • 2016-01-03
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    相关资源
    最近更新 更多