正则表达式不区分大小写和 with/without 空格

regex case insensitive and with/without whitespace

我不太了解正则表达式模式,在阅读了所有维基和参考资料后,我发现我在更改单词检测和突出显示的模式时遇到了问题。

我在另一个 Whosebug 答案上找到了一个函数,它完成了它需要的一切,但现在我发现它遗漏了一些东西

函数为:

function ParserGlossario($texto, $termos) {

    $padrao = '<a href="#" class="termo"></a>';

    if (empty($termos)) {
        return $texto;
    }

    if (is_array($termos)) {
        $substituir = array();
        $com = array();

        foreach ($termos as $key => $value) {
            $key = $value;
            $value = $padrao;
          //  $key = '([\s])(' . $key . ')([\s\.\,\!\?\<])';
            $key = '([\s])(' . $key . ')([\s\.\,\!\?\<])';
            $substituir[] = '|' . $key . '|ix';
            $com[] = empty($value) ? $padrao : $value;
        }

        return preg_replace($substituir, $com, $texto);

    } else {

        $termos = '([\s])(' . $termos . ')([\s])';

        return preg_replace('|'.$termos.'|i', $padrao, $texto);

    }
}

有些词没有被突出显示(标有红色箭头的那些):

我不知道它是否有帮助,但这是用于搜索文本的 "terms" 数组:

EDIT. 正在搜索的字符串只是纯文本:

Abaxial Xxxxx acaule Acaule xxxxxx xxx; xxxxx xxx Abaxial esporos. abaxial

编辑。 添加了 PHP 代码 fiddle

http://phpfiddle.org/main/code/079ad24318f554d9f2ba

有什么帮助吗?我真的不太了解正则表达式...

尝试

$key = '(^|\b)(' . $key . ')\b';

插入

$key = '([\s])(' . $key . ')([\s\.\,\!\?\<])';

应该有帮助。你们的比赛还是会在第二组,不会有第三组,我觉得第一组不应该动,所以我相信

$padrao = '<a href="#" class="termo"></a>';

最好是

$padrao = '<a href="#" class="termo"></a>';

忘记了(抱歉): 改变

$substituir[] = '|' . $key . '|ix';

$substituir[] = '#' . $key . '#ix';

而且我会使用字符串

$com = empty($value) ? $padrao : $value;

而不是数组,在这种情况下不需要它。

让我们一起看看 $key 的值,例如数组元素 acaule.

([\s])(acaule)([\s\.\,\!\?\<])
  1. 有3对(...)定义了3个标记组。

  2. 第一个标记组匹配任何白色space字符。如果字符串开头没有像 for Abaxial 这样的白色 space 字符,则忽略该词。

    \s 放入字符 class 中,即在 [...] 中并不是真正需要的,因为 \s 本身就是一个字符class。 ([\s])(\s) 相等。

  3. 第二个标记组只匹配数组中的单词。

  4. 第三个标记组匹配

    • 任一白色space字符,
    • 或句号,
    • 或逗号,
    • 或感叹号,
    • 或问号,即标准标点符号,
    • 或左尖括号(来自 HTML 或 XML 标签)。


    分号或冒号不匹配,其他非单词字符也被忽略以进行肯定匹配。

    如果字符串末尾有 none 个像 for abaxial 这样的字符,则搜索是否定的。

    顺便说一句:([\s.,!?<]) 等于 ([\s\.\,\!\?\<]),因为只有 \](总是)和 -(取决于位置)必须是在字符 class 定义中使用反斜杠进行转义,以解释为文字字符。好吧,[ 也应该在 [...] 中用反斜杠转义以便于阅读。

所以很清楚为什么字符串开头的Abaxial和字符串结尾的abaxial不匹配。

但是为什么Acaule不匹配呢?

好吧,这个词 acaule 左边有一个 space 左边和一个 space 右边,这是正匹配所必需的。所以 acaule 的 space 权利已经被用于这个正匹配。因此对于Acaule,这个词已经没有白色space字符了。

\b表示词边界不匹配任何可能与\W*?而不是([\s])([\s\.\,\!\?\<])一起使用的字符以避免匹配子字符串一句话。

可能是这样的

$key = '(\W*?)(\b' . $key . '\b)(\W*?)';

\W*?表示任何字字符0次或多次非贪婪。

\W? 表示任何 non 单词字符 0 次或 1 次,如果更适合替换,也可以用于第一和第三捕获组。

但是什么是正确的搜索字符串取决于您想要的替换结果。

我根本没有安装 PHP 解释器,因此无法尝试您的 PHP 代码在替换时的作用以及您希望在替换完成后看到的内容在提供的示例字符串上。