PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Модератор: Модераторы разделов

Аватара пользователя
Anguis
Сообщения: 212
ОС: Manjaro 17

PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Сообщение Anguis »

Здравствуйте камрады! После перехода по php 5.3.3 столкнулся с проблемой регулярок и кириллицы. Я знаю, что об этом много слов сказано и гугль я весь прекопал вдоль и поперек, но ни ответа ни привета по моей проблеме я не нашел.
В свое время что-бы нормально работать с регулярками и русскими символами я перешел на utf-8 (еще когда под виндой работал). Ан не тут-то оно было.. Собственно имеем:

Код: Выделить всё

bash-4.1$ uname -a
Linux 2.6.32.11-pclos2.bfs #1 SMP PREEMPT Wed Apr 7 13:33:19 CDT 2010 i686 i686 i386 GNU/Linux

bash-4.1$ locale -a|grep ru
ru
ru_RU
ru_RU.CP1251
ru_RU.ISO-8859-5
ru_RU.KOI8-R
ru_RU.UTF-8
russian
ru_UA
ru_UA.CP1251
ru_UA.ISO-8859-5
ru_UA.KOI8-R
ru_UA.KOI8-U
ru_UA.UTF-8

bash-4.1$ php -i|grep -E "ru|Version"
PHP Version => 5.3.3
PHP Version => 5.3.3
LC_PAPER => ru_RU.UTF-8
LC_ADDRESS => ru_RU.UTF-8
LC_MONETARY => ru_RU.UTF-8
LC_NUMERIC => ru_RU.UTF-8
LC_TELEPHONE => ru_RU.UTF-8
GP_LANGUAGE => ru
LC_MESSAGES => ru_RU.UTF-8
LC_IDENTIFICATION => ru_RU.UTF-8
LC_COLLATE => ru_RU.UTF-8
LANG => ru_RU.UTF-8
GDM_LANG => ru_RU.UTF-8
LC_MEASUREMENT => ru_RU.UTF-8
LANGUAGE => ru_RU.UTF-8:ru:en_US:en
LC_CTYPE => ru_RU.UTF-8
LC_TIME => ru_RU.UTF-8
LC_NAME => ru_RU.UTF-8
_SERVER["LC_PAPER"] => ru_RU.UTF-8
_SERVER["LC_ADDRESS"] => ru_RU.UTF-8
_SERVER["LC_MONETARY"] => ru_RU.UTF-8
_SERVER["LC_NUMERIC"] => ru_RU.UTF-8
_SERVER["LC_TELEPHONE"] => ru_RU.UTF-8
_SERVER["GP_LANGUAGE"] => ru
_SERVER["LC_MESSAGES"] => ru_RU.UTF-8
_SERVER["LC_IDENTIFICATION"] => ru_RU.UTF-8
_SERVER["LC_COLLATE"] => ru_RU.UTF-8
_SERVER["LANG"] => ru_RU.UTF-8
_SERVER["GDM_LANG"] => ru_RU.UTF-8
_SERVER["LC_MEASUREMENT"] => ru_RU.UTF-8
_SERVER["LANGUAGE"] => ru_RU.UTF-8:ru:en_US:en
_SERVER["LC_CTYPE"] => ru_RU.UTF-8
_SERVER["LC_TIME"] => ru_RU.UTF-8
_SERVER["LC_NAME"] => ru_RU.UTF-8
_ENV["LC_PAPER"] => ru_RU.UTF-8
_ENV["LC_ADDRESS"] => ru_RU.UTF-8
_ENV["LC_MONETARY"] => ru_RU.UTF-8
_ENV["LC_NUMERIC"] => ru_RU.UTF-8
_ENV["LC_TELEPHONE"] => ru_RU.UTF-8
_ENV["GP_LANGUAGE"] => ru
_ENV["LC_MESSAGES"] => ru_RU.UTF-8
_ENV["LC_IDENTIFICATION"] => ru_RU.UTF-8
_ENV["LC_COLLATE"] => ru_RU.UTF-8
_ENV["LANG"] => ru_RU.UTF-8
_ENV["GDM_LANG"] => ru_RU.UTF-8
_ENV["LC_MEASUREMENT"] => ru_RU.UTF-8
_ENV["LANGUAGE"] => ru_RU.UTF-8:ru:en_US:en
_ENV["LC_CTYPE"] => ru_RU.UTF-8
_ENV["LC_TIME"] => ru_RU.UTF-8
_ENV["LC_NAME"] => ru_RU.UTF-8

И такой скриптик, написанный в кодировке utf-8, в разных вариантах исполнения:

Код: Выделить всё

$str = preg_replace('/[^\w ]/i','','ркакшу пфа4рай32 ., гоку74');
echo $str; //Выводит: 432  74

setlocale(LC_ALL, "ru_RU.UTF-8");
$str = preg_replace('/[^\w ]/i','','ркакшу пфа4рай32 ., гоку74');
echo $str; //Выводит: 432  74

setlocale(LC_ALL, "russian");
$str = preg_replace('/[^\w ]/i','','ркакшу пфа4рай32 ., гоку74');
echo $str; //Выводит: �как�� п�а4�ай32  гок�74

Третий вариант как-бы срабатывает, но я не могу ни как понять, почему в строке вывода некоторые символы заменяются на непонятно что. Пока я для себя нашел выход такой:

Код: Выделить всё

$str = preg_replace('/[^\p{L}0-9 ]/iu','','ркакшу пфа4рай32 ., гоку74');
echo $str; //Выводит: ркакшу пфа4рай32  гоку74  Т.е. то, что нужно

Но всё-ж хочется разобраться, почему в третьем варианте паттерн срабатывает как-бы, но некоторые символы заменяются, а в первых двух русские буквы вообще за буквенные символы не считаются?
И еще, если кто подбросит ссыль на более подробное описание юникодных классов, которые можно использовать с модификатором u (типа этого - \p{L}) - БУДУ ОЧЕНЬ БЛАГОДАРЕН!
Спасибо сказали:
Аватара пользователя
Anguis
Сообщения: 212
ОС: Manjaro 17

Re: PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Сообщение Anguis »

Про свойства Unicode нашел - http://www.php.net/manual/ru/regexp.reference.unicode.php
В эту-же проблему хотелось-бы добавить то что в кодировке UTF-8 не работают strtoupper и strtolower для русских букв.. Как решить? У кого какие мысли?
Спасибо сказали:
neol
Сообщения: 600
ОС: Debian Stable

Re: PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Сообщение neol »

Anguis писал(а):
22.03.2011 15:19
В эту-же проблему хотелось-бы добавить то что в кодировке UTF-8 не работают strtoupper и strtolower для русских букв.. Как решить? У кого какие мысли?

$str = mb_strtoupper($str, 'UTF-8');

http://www.php.net/manual/en/book.mbstring.php
Спасибо сказали:
Аватара пользователя
Anguis
Сообщения: 212
ОС: Manjaro 17

Re: PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Сообщение Anguis »

neol писал(а):
22.03.2011 16:08
Anguis писал(а):
22.03.2011 15:19
В эту-же проблему хотелось-бы добавить то что в кодировке UTF-8 не работают strtoupper и strtolower для русских букв.. Как решить? У кого какие мысли?

$str = mb_strtoupper($str, 'UTF-8');

http://www.php.net/manual/en/book.mbstring.php

А если нет mb? И нет возможности поставить? На хостингах типа 1gb.ru и подобных..
Спасибо сказали:
Аватара пользователя
Anguis
Сообщения: 212
ОС: Manjaro 17

Re: PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Сообщение Anguis »

Мне интересно, это чей баг? Это из-за разрабов php или Unicode? Почему так происходит, и какие стандартные методы решения есть (без сторонних либ)? Нужели только arrry('А'=>'а','Б'=>'б'...) и т.п.?
Спасибо сказали:
neol
Сообщения: 600
ОС: Debian Stable

Re: PHP 5.3.x, preg_replace, UTF-8 и русские буквы

Сообщение neol »

Anguis писал(а):
22.03.2011 17:31
Мне интересно, это чей баг? Это из-за разрабов php или Unicode?

Это фича php. В 6 версии обещают сделать все coca cola.

Anguis писал(а):
22.03.2011 17:31
Почему так происходит, и какие стандартные методы решения есть (без сторонних либ)? Нужели только arrry('А'=>'а','Б'=>'б'...) и т.п.?

Стандартное решение - mbstring.
Спасибо сказали: