$str = 'کس نے موسیٰ کے بارے میں سنا ہے؟';
$str = preg_replace('/(?<=\b)موسیٰ(?=\b)/u', 'Musa', $str);
$str = preg_replace('/(?<=\b)سنا(?=\b)/u', 'suna', $str);
echo $str;
无法替换موسیٰ
。它应该提供کس نے Musa کے بارے میں suna ہے؟
,而是提供کس نے موسیٰ کے بارے میں suna ہے؟
。
所有以ٰ
结尾的字词都会发生这种情况,例如تعالیٰ
。它适用于ٰ
位于单词中间的单词(没有单词以ٰ
开头)。这是否意味着\b
不能与ٰ
一起使用?这是一个错误吗?
答案 0 :(得分:1)
原因是字边界在以下位置匹配:
- 在字符串中的第一个字符之前,如果第一个字符是单词字符。
- 在字符串中的最后一个字符之后,如果最后一个字符是单词字符。
- 字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符。
“违规”符号是U+0670
ARABIC LETTER SUPERSCRIPT ALEF
属于 \p{Mn}
(非间距标记Unicode类别),因此非单词符号。如果\b
前面有一个属于\w
的字符(字母,数字,_
),则$str = 'کس نے موسیٰ کے بارے میں سنا ہے؟';
$str = preg_replace('/(?<!\w)موسیٰ(?!\w)/u', 'Musa', $str);
$str = preg_replace('/(?<!\w)سنا(?!\w)/u', 'suna', $str);
echo $str; // => کس نے Musa کے بارے میں suna ہے؟
将匹配。
使用明确的边界,只有在搜索短语之前/后面没有单词字符时才使用:
(?<!\w)
请参阅PHP demo。
(?!\w)
是一个负面的背后隐藏,确保在随后的消费模式之前没有单词char,而Array.reduce()
是一个负向前瞻,确保在前一个消费之后没有单词char图案。
答案 1 :(得分:0)
\b
和\B
...是根据\w
和\W
定义的。
\w
匹配属于ASCII表的字符,但使用(*UCP)
选项或u
unicode修饰符定义\w
更改时,还包括来自其他语言的所有其他字母但不是组合标记。
这样说,\b
永远不会匹配ٰ
这样的标记看到非单词字符的位置,因为标记本身被视为非单词字符。
你想要做的更像是弄清楚在موسیٰ
之前或之后是否有任何非单词字符,因此断言\S
元字符可以完成这项任务:
(?<!\S)موسیٰ(?!\S)
完成此类任务的另一种方法是使用ICU库transliterating整个输入字符串删除所有重音,然后尝试匹配不包含组合标记{{1}的单词موسی
}}:
ٰ
输出:
<?php
$strings = [
'is' => 'کس نے موسیٰ کے بارے میں سنا ہے؟', // input string
'wts' => 'موسیٰ' // word to search
];
array_walk($strings, function(&$value) {
$value = transliterator_transliterate('[:Nonspacing Mark:] Remove;', $value);
});
// word boundaries now can be used
echo preg_replace('/\b' . $strings['wts'] . '\b/u', 'musa', $strings['is']);