我想在文本中标记所有单词,但标记内的单词除外。 基于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>
知道为什么会发生这种情况以及如何解决这个问题? 感谢
答案 0 :(得分:1)
这里有几件事:
u
。\p{M}
。所以正则表达式增长了:
$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>
答案 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>