php 另一个Unicode preg_replace()问题

nmpmafwu  于 2023-06-21  发布在  PHP
关注(0)|答案(3)|浏览(154)

我读过很多解释如何处理Unicode字符的帖子,但没有一个建议对我有用。
我的php页面读取一个包含高阶字符串的文件,例如“Mötor”。我想将字符串转换为“正常”字符,例如“Motor”。
这就是我所尝试的:

$source = "Mötor";
$test = preg_replace('/[^\w\d\p{L}]/u', "", $source); // Returns null.
$test = preg_replace('/[^\w\d\p{L}]/u', "", htmlentities($source)); // Returns "".
$test = preg_replace("/&([a-z])[a-z]+;/i", "$1", $source); // Returns "Mötor".
$test = preg_replace("/&([a-z])[a-z]+;/i", "$1", htmlentities($source)); // Returns "".
$test = iconv('utf-8', 'ascii//TRANSLIT', $source); // Returns false.

我被难住了。谢谢!

hmtdttj4

hmtdttj41#

这被称为“音译”,intl的Transliterator将比将正则表达式拼凑在一起更好地工作。

$tests = [ "Mötor" ];

$tl = Transliterator::create('Latin-ASCII;');
foreach($tests as $str) {
    var_dump(
        $tl->transliterate($str)
    );
}

输出:

string(5) "Motor"
m1m5dgzv

m1m5dgzv2#

一个行之有效的方法:

<?php
$source = "Mötor, šeřík, Προϊστορία, Україна";
var_dump( $source);
var_dump( preg_replace("/\p{Mn}/u", '',
            Normalizer::normalize( $source, Normalizer::FORM_D )));
?>

输出.\SO\76446827.php

string(54) "Mötor, šeřík, Προϊστορία, Україна"
string(50) "Motor, serik, Προιστορια, Украіна"

参考资料(阅读):

  • Unicode Normalization Forms
  • 正则表达式:Unicode分类
  • \p{M}\p{Mark}:要与另一个字符组合的字符(例如,重音符号、变音符号、封闭框等)。- \p{Mn}\p{Non_Spacing_Mark}:一种不占用额外空间而与另一个字符组合在一起的字符(例如,重音元音变音等)。
  • \p{Mc}\p{Spacing_Combining_Mark}:用来和另一个字符组合的字符,它占用了额外的空间(在许多东方语言中是元音符号)。
  • \p{Me}\p{Enclosing_Mark}:一种字符,它包含与之组合的字符(圆形、方形、键帽等)。
  • PHP手册:Unicode character properties注意正则表达式中支持Unicode的/u选项
    注意:测试字符串包含各种脚本的重音字符(包括 WesternEastern LatinGreekCyrillic),以证明所用正则表达式的 * 脚本独立性 *:
  • ö(U+00 F6,* 带分音符的拉丁文小写字母O *)
  • š(U+0161,* 带卡隆的拉丁文小写字母S *)
  • ř(U+0159,* 带卡隆的拉丁文小写字母R *)
  • í(U+00 ED,* 带锐音符的拉丁文小写字母I *)
  • ϊ(U+03 CA,* 带Dialytika的希腊文小写字母Iota *)
  • ί(U+03 AF,* 带Tonos的希腊文小写字母Iota *)
  • ї(U+0457,* 西里尔文小写字母Yi*)
flseospp

flseospp3#

对我有效的解决方案是在指定UTF-8的同时重新保存文件(使用记事本)。
根据其他人的评论,另一种解决方案是使用Transliterator。然而,这是一个php扩展,没有安装在我使用的(共享)服务器上。

相关问题