我有a PHP 5.3 script显示我网站的用户,并希望用其旧名称替换某个俄罗斯城市(存储在PostgreSQL 8.4.7数据库中的UTF8 + CentOS 5.5 / 64位Linux中)(它是内幕笑话:
preg_replace('/Волгоград/iu', 'Сталинград', $city);
不幸的是,这仅适用于完全匹配:Волгоград。
这不适用于其他情况,例如ВОЛГОГРАД或волгоград。
如果我将源代码修改为
preg_replace('/[Вв]олгоград/iu', 'Сталинград', $city);
然后它会抓住上面的第二个案例。
有人知道它发生了什么以及如何解决它(假设我不想为每个字母写 [Xx] )?
谢谢! 亚历
更新
# 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
答案 0 :(得分:5)
我无法使用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) "Сталинград"
您的PHP使用哪种PCRE版本?检查phpinfo()
部分pcre
。这就是我系统中的那个:
...
pcre
PCRE (Perl Compatible Regular Expressions) Support => enabled
PCRE Library Version => 8.02 2010-03-19
...
答案 1 :(得分:4)
你可以跳过正则表达式,它在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]."
这引起了我的兴趣,所以I asked a question。
答案 2 :(得分:4)
这个问题解决了这个问题:
setlocale(LC_ALL, 'ru_RU.CP1251', 'rus_RUS.CP1251', 'Russian_Russia.1251');
答案 3 :(得分:2)
我复制+粘贴你的大В
。它确实是U+D092
,而不是普通的拉丁语B
。但是因为它们看起来很相似:ВB
我相信俄语字母被整理到U+0042
的拉丁语B上。
因此要么是PHP预先格式化它,要么PCRE在那里也有些不精确。测试您的print PCRE_VERSION;
并查看更改日志。
无论如何,为了避免这个问题,我建议你只使用小写字母。它们更可能与拉丁字母不同。
preg_replace('/волгоград/iu', 'Сталинград', $city);
P.S。:笑话里面的笑话!
答案 4 :(得分:1)
在我的盒子上像魅力一样......
<?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?
答案 5 :(得分:1)
也许试试:mb_eregi_replace http://www.php.net/manual/en/function.mb-eregi-replace.php
mb_eregi_replace - 使用忽略大小写的多字节支持替换正则表达式
答案 6 :(得分:0)
只是猜测,但明确地将字符串编码为unicode可能会有所帮助:
preg_replace('/Волгоград/iu', utf8_encode('Сталинград'), $city);
答案 7 :(得分:0)
实际上在Windows上使用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成功替换(case-initiveitively)'гъз'并返回UTF-8版本。
问候!
答案 8 :(得分:0)
对于那些支持巨大遗留代码库的人来说,与charset&amp;编码问题,没有转换代码字符集的选项 - 这是一个答案:
//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,但是当您使用庞大的代码库/数据库等时,它不是一个选项