PHP: без учета регистра preg_replace кириллической строки в UTF8 - PullRequest
4 голосов
/ 28 марта 2011

У меня скрипт PHP 5.3 , отображающий пользователей моего веб-сайта, и я хотел бы заменить определенный русский город (хранящийся в UTF8 в базе данных PostgreSQL 8.4.7 + CentOS 5.5 / 64 бит Linux) его старое имя (это инсайдерская шутка):

preg_replace('/Волгоград/iu', 'Сталинград', $city);

К сожалению, это работает только для точных совпадений: Волгоград .

Это не работает для других случаев, таких как ВОЛГОГРАД или волгоград .

Если я изменю свой исходный код на

preg_replace('/[Вв]олгоград/iu', 'Сталинград', $city);

тогда он поймает второй случай выше.

Кто-нибудь знает, что происходит и как это исправить (при условии, что я не хочу писать [Xx] для каждое письмо)?

Спасибо! Alex

UPDATE:

# rpm -qa|grep php
php53-bcmath-5.3.3-1.el5
php53-gd-5.3.3-1.el5
php53-common-5.3.3-1.el5
php53-pdo-5.3.3-1.el5
php53-mbstring-5.3.3-1.el5
php53-xml-5.3.3-1.el5
php53-5.3.3-1.el5
php53-cli-5.3.3-1.el5
php53-pgsql-5.3.3-1.el5

# rpm -qa|grep pcre
pcre-6.6-2.el5_1.7

Ответы [ 9 ]

5 голосов
/ 28 марта 2011

Я не могу воспроизвести вашу проблему с PHP 5.3.3 (PHP 5.3.3-1ubuntu9.3 with Suhosin-Patch (cli)):

$str1 = 'Волгоград';
$str2 = 'ВОЛГОГРАД';
$str3 = 'волгоград';

var_dump(preg_replace('/Волгоград/iu', 'Сталинград', $str1));
var_dump(preg_replace('/Волгоград/iu', 'Сталинград', $str2));
var_dump(preg_replace('/Волгоград/iu', 'Сталинград', $str3));

выходы

string(20) "Сталинград"
string(20) "Сталинград"
string(20) "Сталинград"

Какую версию PCRE использует ваш PHP? Проверьте вас phpinfo() на pcre -секцию. Это то, что в моей системе:

...
pcre

PCRE (Perl Compatible Regular Expressions) Support => enabled
PCRE Library Version => 8.02 2010-03-19
...
4 голосов
/ 12 августа 2013

Это решило проблему:

setlocale(LC_ALL, 'ru_RU.CP1251', 'rus_RUS.CP1251', 'Russian_Russia.1251');
4 голосов
/ 28 марта 2011

Вы можете пропустить регулярное выражение, у меня это работает в PHP 5.2.11:)

$city = 'Unfortunately this only works for exact matches: Волгоград.

This does not work for other cases, like ВОЛГОГРАД or волгоград.';

echo str_ireplace('Волгоград', '[found]', $city);

выход

"Unfortunately this only works for exact matches: [found].

This does not work for other cases, like [found] or [found]."

Это заинтриговало меня, поэтому Я задал вопрос .

2 голосов
/ 28 марта 2011

копирую + вставляю твой большой В. Это действительно U+D092, а не обычный латинский B. Но так как они очень похожи: ВB Я считаю, что русская буква сопоставлена ​​с латинской буквой B U+0042.

Так что либо PHP предварительно форматирует его, либо, может быть, PCRE и там несколько неточен. Проверьте свой print PCRE_VERSION; и посмотрите список изменений.

В любом случае, чтобы избежать проблемы, я бы предложил вам использовать только строчные буквы. Они чаще отличаются от латинского алфавита.

preg_replace('/волгоград/iu', 'Сталинград', $city);

П.С .: Злая шутка внутри!

1 голос
/ 28 марта 2011

Возможно попробуйте: mb_eregi_replace http://www.php.net/manual/en/function.mb-eregi-replace.php

mb_eregi_replace - заменить регулярное выражение многобайтовой поддержкой, игнорируя регистр

1 голос
/ 28 марта 2011

Работает как брелок на моем ящике ...

<?php
    $city = 'Волгоград';
    var_dump(preg_match('/волгоград/ui', $city));
    var_dump(preg_match('/ВОЛГОГРАД/ui', $city));
    var_dump(preg_replace('/волгоград/ui', 'Сталинград', $city));
    var_dump(preg_replace('/ВОЛГОГРАД/ui', 'Сталинград', $city));

Вывод:

int 1
int 1
string 'Сталинград' (length=20)
string 'Сталинград' (length=20)

Вы уверены, что входные данные ($ city) находятся в UTF8?

0 голосов
/ 13 июня 2015

для тех, кто поддерживает огромную унаследованную базу кода, борется с проблемами кодировки и кодирования и не имеет возможности конвертировать кодовую таблицу - вот ответ:

//for 
setlocale(LC_ALL, 'ru_RU.cp1251');  
//(or any other locale) to take effect, 
//you MUST generate system locale, i.e.

sudo su
#view supported locales
#less /usr/share/i18n/SUPPORTED
echo "ru_RU.cp1251 CP1251" >> /var/lib/locales/supported.d/local
dpkg-reconfigure locales
exit

#and (for ubuntu/debian)

apt-get install php5-intl

хотя вы можете переписать свое регулярное выражение для использования некоторых трюков utf, преобразовать свой код в utf, это не вариант, когда вы работаете с огромной базой кода / базой данных и т. Д.

0 голосов
/ 19 апреля 2011

На самом деле с PHP 5.2.x на окнах выбранный для решенного ответа у меня не работал.

Мне пришлось перейти на Windows-1251, чтобы он заработал.

Вот пример:

$new_content = preg_replace(iconv('UTF-8', 'Windows-1251', "/\bгъз\b/i"), iconv('UTF-8', 'Windows-1251', "YYYYYY"), iconv('UTF-8', 'Windows-1251', "ти си gyz gyz гъз ГЪЗ gyzgyz гЪз gyz"));
$new_content = iconv('Windows-1251', 'UTF-8', $new_content);

Приведенный выше пример успешно заменит (без учета регистра) 'гъз' на YYYYYY и вернет вам версию UTF-8.

Привет!

0 голосов
/ 28 марта 2011

Просто угадать, но явное кодирование строки в юникод может помочь:

preg_replace('/Волгоград/iu', utf8_encode('Сталинград'), $city);
...