我有这两个示例字符串:
$a=‘侏儒’; $B=‘侏儒’;
它们在视觉上看起来是一样的,但第三个字符不同:
在字符串$a上是Unicode 227(带波浪符号的拉丁文小写字母a),在字符串$b上是Unicode 97(拉丁文小写字母a)+Unicode 771(组合波浪符号)
如何检测字符串是否包含任何组合字符,而不是"常规"字符?
我try 用函数"order()"判断字符串中的所有字符,但没有成功.
我有这两个示例字符串:
$a=‘侏儒’; $B=‘侏儒’;
它们在视觉上看起来是一样的,但第三个字符不同:
在字符串$a上是Unicode 227(带波浪符号的拉丁文小写字母a),在字符串$b上是Unicode 97(拉丁文小写字母a)+Unicode 771(组合波浪符号)
如何检测字符串是否包含任何组合字符,而不是"常规"字符?
我try 用函数"order()"判断字符串中的所有字符,但没有成功.
请注意,ord
在ASCII范围内运行,仅匹配单字节编码的字符,对0-255范围之外的多字节Unicode字符没有帮助.
您可以使用带有Unicode u
标志的preg_match
,然后匹配适当的Unicode字符范围.在这种情况下,\p{M}
将完成这项工作.它代表:
\p{M}或\p{Mark}:要与另一个字符组合的字符(例如重音、元音、包围方框等).
适用范围如下:
$a = 'Anão';
$b = 'Anão';
var_dump([
preg_match('~\p{M}~u', $a), // = 0
preg_match('~\p{M}~u', $b) // = 1
]);
返回0
和1
:您的$b
字符串有一个组合变音符号.然后,您将判断if(preg_match('~\p{M}~u', $str))
以找出字符串是否包含组合变音符号.
这将匹配所有类型的组合变音符号.如果您想要确定组合元音变音符号所属的确切字符类别,它将在{Mn}
的范围内:
\p{Mn}或\p{Non_Spacing_Mark}:在不占用额外空格的情况下与另一个字符组合的字符(如重音、变音等).
如果你的问题源于"how do I make these strings equivalent",因为当$a != $b
看起来一样的时候,显然是有问题的.PHP有一个方便的Normalizer类,用于将Unicode字符串转换为它们的canonical forms.用法如下:
Normalizer::normalize('Anão', Normalizer::NFC); // Single Char, Default
Normalizer::normalize('Anão', Normalizer::NFD); // Combined
在这里,NFC(默认)或Normalization Form C代表"Canonical Decomposition, followed by Canonical Composition",首先将字符拆分成几个部分,然后尽可能地组合成一个字符.同样,NFD,Normalization Form D (NFD)代表"Canonical Decomposition",其中变音符号变成单独的组合字符,等等.
如果您规范化了所有可能包含变音符号的字符串,无论是在源数据中还是在对其进行的查询中,我怀疑您最初的问题都不会出现.
附注:请参阅regular-expressions.info获取有用的Unicode reference for Regex小抄,以及维基百科上的Unicode character property / Categories表格.