正则表达式匹配标签外的所有单词和PHP上的重音

时间:2014-09-16 05:01:06

标签: php regex diacritics words

我想在文本中标记所有单词,但标记内的单词除外。 基于here的想法,我能够完成以下任务:

preg_replace("/(\b(\p{L}+)\b)(?!([^<]+)?>)/", "<mark>$1</mark>", $input);

除了使用重音之外,其他一些奇怪的行为除外。例子:

lorem ipsúm dolor <a href="#" title="sit">sit</a> amet consectetur
[OK] => <mark>lorem</mark> <mark>ipsúm</mark> <mark>dolor</mark> <a href="#" title="sit"><mark>sit</mark></a> <mark>amet</mark> <mark>consectetur</mark>

ação ipísum
[NOT OK] => <mark>a</mark>çã<mark>o</mark> <mark>ip</mark>í<mark>sum</mark>

知道为什么会发生这种情况以及如何解决这个问题? 感谢

2 个答案:

答案 0 :(得分:1)

一切都那么简单......

这里有几件事:

  1. 您想使用UTF-8修饰符u
  2. 与您的示例文本无关,但是您遗漏了由字母组成的字母组合,如“è”这样的变音符号。这里编码为“e”,后跟combining grave accent。要匹配您需要添加一些可选的\p{M}
  3. 所以正则表达式增长了:

    $input = 'lorem <a href="#">foo</a> ação';
    
    echo preg_replace(
        '/\b((?:\p{L}\p{M}*)+)\b(?!([^<]+)?>)/u',
        "<mark>$1</mark>",
        $input
    );
    

    输出:

    <mark>lorem</mark> <a href="#"><mark>foo</mark></a> <mark>ação</mark>
    

    ...除

    到目前为止这么好,对吗?让我们添加“è”并查看。

    $input = 'lorem <a href="#">foo</a> ação evè';
    

    输出输出:

    <mark>lorem</mark> <a href="#"><mark>foo</mark></a> <mark>ação</mark> <mark>eve</mark>̀
    

    这是不对的。即使在utf-8模式下,简化单词\b仍然有点愚蠢。所以你必须用一些消极的外观替换它。

    虽然我们正在使用它,但我们也使用\pL代替\p{L},因为花括号对于单字母Unicode类别是可选的。


    全部放在一起:

    $input = 'lorem <a href="#">foo</a> ação evè';
    
    echo preg_replace(
        '/(?<![\pL\pM])((?:\pL\pM*)+)(?![\pL\pM])(?!([^<]+)?>)/u',
        "<mark>$1</mark>",
        $input
    );
    

    输出:

    <mark>lorem</mark> <a href="#"><mark>foo</mark></a> <mark>ação</mark> <mark>evè</mark>
    

    https://eval.in/194139的演示。

答案 1 :(得分:0)

使用u修饰符:

$arr = Array('orem ipsúm dolor <a href="#" title="sit">sit</a> amet consectetur','ação ipísum');
foreach($arr as $input) {
    echo preg_replace("/(\b(\p{L}+)\b)(?!([^<]+)?>)/u", "<mark>$1</mark>", $input),"\n";
    //                                       here __^
}

<强>输出:

<mark>orem</mark> <mark>ipsúm</mark> <mark>dolor</mark> <a href="#" title="sit"><mark>sit</mark></a> <mark>amet</mark> <mark>consectetur</mark>
<mark>ação</mark> <mark>ipísum</mark>