在PCRE/PHP中匹配Unicode字母字符

17

我正在尝试编写一个相对宽松的 PHP 名称验证器,我的第一次尝试包括以下模式:

// unicode letters, apostrophe, hyphen, space
$namePattern = "/^([\\p{L}'\\- ])+$/";

这最终会传递给对preg_match()的调用。据我所知,这适用于您的普通ASCII字母表,但似乎在处理像Ă或张这样的更复杂字符时出现问题。

模式本身有问题吗?也许我期望\p{L}做更多的工作,而实际上它并没有做到?

还是与输入传递方式有关?我不确定它是否相关,但我确保在表单页面上指定了UTF8编码。

5个回答

33

我觉得问题比那更简单:你忘记指定u 修饰符了。Unicode字符属性仅在UTF-8模式下可用

你的正则表达式应该是:

// unicode letters, apostrophe, hyphen, space
$namePattern = '/^[-\' \p{L}]+$/u';

@chx:给我返回 int(0)。你的文件可能没有使用 UTF-8 编码。 - NikiC
我使用了我在答案中展示的utf8ToUnicode例程来验证我的文件中的代码点。 - chx
@chx:在这种情况下,我不知道。如果没有修饰符,它对我不起作用,但是有了修饰符就可以工作。由于PHP没有适当的多字节支持,因此编码问题很常见。 - NikiC
@Jeff Lee:它表示该字符串应被视为UTF-8字符串。即:一个UTF-8字符可能由多个字节组成。通常情况下,PCRE会将每个单独的字节与您的正则表达式进行匹配。但在UTF-8模式下,它将组合这些字节并进行匹配 ;) - NikiC
+1,对于完成,另一种在此模式中启用Unicode属性的方法是:(*UTF)(*UCP)^[-\' \p{L}]+$(请参见PCRE的特殊模式开头修饰符)。 - zx81
显示剩余2条评论

1
如果你想用新的模式替换Unicode的旧模式,你应该写成:

new pattern


$text = preg_replace('/\bold pattern\b/u', 'new pattern', $text);

所以这里的关键是 u 修饰符。

注意:您的服务器 php 版本 应至少为 PHP 4.3.5,如 php.net | 模式修饰符 所述。

u (PCRE_UTF8) 此修饰符打开了 PCRE 的其他功能,与 Perl 不兼容。模式字符串被视为 UTF-8。此修饰符可在 Unix 上从 PHP 4.1.0 或更高版本上使用,在 win32 上从 PHP 4.2.3 开始使用。自 PHP 4.3.5 以来,将检查模式的 UTF-8 有效性。

感谢 AgreeOrNot 给我提供了这个关键点,详见 preg_replace 在阿拉伯语中匹配整个单词

我尝试了一下,在本地主机上可以运行,但在远程服务器上无法运行,后来发现php.net开始在PHP 4.3.5中使用u修饰符。我升级了php版本,然后它就可以工作了。
重要的是要知道,这种方法对阿拉伯语用户(عربي)非常有帮助,因为Unicode是阿拉伯语言最好的编码方式,如果不使用u修饰符,替换将无法正常工作,请参见下一个示例,它应该可以与您一起使用。 $text = preg_replace('/\bمرحبا بك\b/u', 'NEW', $text);

0
首先,如果您在编写这些内容时使用单引号而不是双引号,那么您的生活将变得更加轻松 - 您只需要一个反斜杠。其次,组合标记\pM也应该包括在内。如果您发现某个字符没有匹配,请找出它的Unicode代码点,然后您可以使用http://www.fileformat.info/info/unicode/来确定它的位置。我发现http://hsivonen.iki.fi/php-utf8/是UTF-8属性调试时非常有价值的工具(别忘了在尝试查找之前将其转换为十六进制:array_map('dechex', utf8ToUnicode($text)))。
例如,Ă的Unicode编码是http://www.fileformat.info/info/unicode/char/0102/index.htm,它属于Lu类,因此L应该与它匹配,而对我来说确实匹配了。另一个字符是http://www.fileformat.info/info/unicode/char/5f20/index.htm,也是字母,并且对我来说确实匹配。你是否已经编译好Unicode字符表了呢?


0

-2
<?php preg_match('/[a-zığüşöç]/u',$title)  ?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接