Preg_match()和多字节字符


preg_match() and multibyte characters

我试图用preg_match处理波兰字符,但是有些东西是非常错误的。

这些是我的尝试:

  1. 不含u修饰符:

    preg_match("@^[0-9A-ZĄąĆćĘꣳÓ󯿏źŃńŚś'-'.', ]{5,35}$@i", $valuesId)
    
  2. u修饰符:

    preg_match("@^[0-9A-ZĄąĆćĘꣳÓ󯿏źŃńŚś'-'.', ]{5,35}$@iu", $valuesId)
    

但是像Żółkiewski, Zielona GóraRównina这样的词不能不通过。

有谁知道如何在不改变服务器设置的情况下正确处理它?

您的正则表达式工作正常。但前提是角色以UTF-8的身份出现。您是否在一个字符编码设置为ISO-8859-2(中欧ISO拉丁2)的系统中工作,这是波兰字符的ISO标准字符集?看看我放在一起的这个示例/调试代码。请注意,我尝试了mb_detect_encodingmb_convert_encoding,但不清楚这是否有帮助或伤害。如果这部分代码让人感到困惑,可以随意注释掉:

// Set a test array.
$test_array = array();
$test_array[] = 'Żółkiewski';
$test_array[] = 'Zielona Góra';
$test_array[] = 'Równina';
// Get the contenst of the URL via file_get_contents.
if (file_exists('zzz_polish.txt')) {
  $test_file_array = file('zzz_polish.txt');
}
// Set the header for debugging output.
header('Content-Type: text/plain; charset=utf-8');
// Roll through the test array.
foreach ($test_file_array as $valuesId) {
  // Run a regex to detect Polish UTF-8 characters.
  preg_match("@^[0-9A-ZĄąĆćĘꣳÓ󯿏źŃńŚś'-'.', ]{5,35}$@i", $valuesId, $matches);
  // Set the character encoding to be UTF-8 if it is not already UTF-8.
  if (mb_detect_encoding($valuesId) != 'UTF-8') {
    $valuesId = mb_convert_encoding($valuesId, 'UTF-8', array('ISO-8859-2'));
  }
  // Dump the matches for debugging.
  print_r($matches);
}

现在,如果将其放入扩展名为.php的UTF-8编码文本文件中,结果如下:

Array
(
    [0] => Żółkiewski
)
Array
(
    [0] => Zielona Góra
)
Array
(
    [0] => Równina
)

这是预期的。但是我已经能够重新创建一个条件,它将失败与表面上看似数据放在一个名为zzz_polish.txt的文件中,如下所示:

Żółkiewski
Zielona Góra
Równina

现在,如果我用适当的UTF-8编码保存该文件,它的工作方式就像其中包含test数组的示例一样。但是,如果我通过简单地将文件编码更改为UTF-16来导致它失败,那么在屏幕上我的眼睛上读起来都是一样的,但是输出简单如下:

Array
(
)
Array
(
)
Array
(
)

所以我的猜测是在你的数据链的某个地方有一些文本编码混淆发生。否则你的正则表达式工作得很好。

这些字符真的是多字节的吗?

如在线演示所示,以下代码三次返回1 (TRUE值):
$regex = "@^[0-9A-ZĄąĆćĘꣳÓ󯿏źŃńŚś., -]{5,35}$@i";
echo preg_match($regex,"Żółkiewski")."'n";
echo preg_match($regex,"Zielona Góra")."'n";
echo preg_match($regex,"Równina")."'n";

因此,问题不在于正则表达式,而在于正则表达式所在脚本的编码与提供给正则表达式的输入之间的不匹配。例如,您的脚本可能使用Windows或ISO东欧编码之一…在这种情况下,它们可能根本不是多字节的。许多ide和编辑器都能够转换文本文件的编码。

最好的选择是确保系统的每个组件都使用utf-8:

  • 脚本的编码
  • 脚本发送的头信息
  • meta标签
  • 数据库连接
  • 数据库中的数据

以此类推。如何实现所有这些都是本书一章的主题,超出了本问题的范围。