preg_match()和多字节字符

时间:2014-06-21 21:14:40

标签: php regex preg-match

我试图用preg_match处理波兰字符,但有些事情是错误的。

这些是我的尝试:

  1. 没有u修饰符:

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

    preg_match("@^[0-9A-ZĄąĆćĘꣳÓ󯿏źŃńŚś\-\.\, ]{5,35}$@iu", $valuesId)
    
  3. ŻółkiewskiZielona GóraRównina等词语无法通过。

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

2 个答案:

答案 0 :(得分:1)

你的正则表达式按预期工作。但只有当角色以UTF-8的形式出现时。您是否可能在字符编码设置为ISO-8859-2(中欧ISO拉丁文2)的系统中工作,这是波兰字符的ISO标准字符集?看看我放在一起的这个示例/调试代码。请注意,我尝试使用mb_detect_encoding以及mb_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编码保存该文件,它就像其中包含测试数组的示例一样。但是,如果我通过简单地将文件编码更改为UTF-16来使其失败,那么屏幕上的所有内容都是相同的,但输出结果如下:

Array
(
)
Array
(
)
Array
(
)

所以我猜你的数据链中有一些文本编码混淆正在发生。你的正则表达式效果不错。

答案 1 :(得分:0)

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

如此online demo所示,以下代码三次返回1TRUE值):

$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:

  • 脚本的编码
  • 脚本发送的标题
  • 元标记
  • 与数据库的连接
  • 数据库中的数据

等等。解决如何实现所有这些问题是书籍章节的主题,超出了本问题的范围。