Php preg_替换使用Unicode无法正常工作?

Php preg_替换使用Unicode无法正常工作?,php,unicode,utf-8,preg-replace,Php,Unicode,Utf 8,Preg Replace,我正在使用preg\u replace功能过滤掉一些用户输入。下面的函数应该过滤掉Unicode中的控制字符,但似乎这些字符中的一些被归类为其他类别(标点、空格等),从而允许它们通过过滤。为什么会这样 preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", $message); 下面是一些使用上述方法通过筛选的Unicode U+0085 NEXT LINE (NEL) … U+008C PARTIAL LINE BACKWARD

我正在使用
preg\u replace
功能过滤掉一些用户输入。下面的函数应该过滤掉Unicode中的控制字符,但似乎这些字符中的一些被归类为其他类别(标点、空格等),从而允许它们通过过滤。为什么会这样

preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", $message);
下面是一些使用上述方法通过筛选的Unicode

U+0085  NEXT LINE (NEL)     …
U+008C  PARTIAL LINE BACKWARD   Œ
U+0095  MESSAGE WAITING     •

更换前的安全性如何?还有更好的方法吗?

请在使用
preg\u replace()
之前先尝试一下

preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", utf8_encode($message));
在代码中,您有:

"a…Œ•a"
其中包括:

  • U+2026水平省略号
  • Œ
    U+0152拉丁文大写连字OE
  • U+2022子弹头
正如您所料,
Œ
是一个字母
\p{L}
,另外两个是标点符号
\p{p}
,因此所有这些都是允许的

你被某个资源误导了,其中有人说,
是U+0085,依此类推;事实并非如此。发生这种情况的可能原因是他们编写了一个带有数字字符引用的HTML文件
在其中

在HTML中,字符引用
和#x9F
(又称
€;
Ÿ;
)实际上并不表示代码点为U+0080到U+009F的Unicode字符。而是指Windows代码页1252(西欧)编码中编码形式介于0x80和0x9F之间的字符。代码页1252中的字节0x85是省略号,因此
表示U+2026,而不是U+0085

这是由于历史原因造成的:古代浏览器中的漏洞早于现代人对Unicode的理解,后来被其他人复制并最终被发现。XML不会受到这种异常的影响:在XHTML中,
实际上是U+0085

对于代码点U+0080-U+009F中的实数(不可见,“C1”)控制字符,表达式工作正常:

function unichr($i) { // get character from code point, in UTF-8 string form
    return iconv('UCS-4LE', 'UTF-8', pack('V', $i));
}

$message = 'a'.unichr(0x85).unichr(0x8C).unichr(0x95).'a';
$filtered = preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", $message);
var_dump($filtered);

<<< string(2) "aa"
函数unichr($i){//以UTF-8字符串形式从代码点获取字符
返回iconv('UCS-4LE','UTF-8',包装('V',$i));
}
$message='a'.unichr(0x85).unichr(0x8C).unichr(0x95)。'a';
$filtered=preg_replace(“/[^\p{L}\p{M}\p{N}\p{p}\p{S}]/u”,”,“,$message);
var_转储(已过滤);

不,它将它们转换为其他字符,而不是删除。你能回答我的问题真是我的荣幸。你的丰富知识总是给我留下深刻印象。