如何去除重音符号并将字母变成“普通”的 ASCII 字符? [复制]

Posted

技术标签:

【中文标题】如何去除重音符号并将字母变成“普通”的 ASCII 字符? [复制]【英文标题】:How to remove accents and turn letters into "plain" ASCII characters? [duplicate] 【发布时间】:2011-04-02 08:17:45 【问题描述】:

从字符串中删除重音的最有效方法是什么? ÈâuÑ 变成 Eaun?

是否有我缺少的简单内置方式或正则表达式?

【问题讨论】:

@Peeps:告诉用户搜索 google 违反了 Stack Overflow 的礼仪。如果网站上不存在该问题,那么即使 OP 已经知道答案,对每个人都更好,因为它会增加我们的非重复问题的数量。所以也许下次如果有人用谷歌搜索,他们会发现这个问题,我们会多一个用户。 @Andreas 好点。但是,这肯定是一个 SO 重复,所以 Peeps 有点小意思:) 不过,我现在懒得搜索它。 【参考方案1】:

我找到了一个适用于我所有测试用例的解决方案(复制自 http://php.net/manual/en/transliterator.transliterate.php):

var_dump(transliterator_transliterate('Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove',
    "A æ Übérmensch på høyeste nivå! И я люблю PHP! есть. fi ¦"));
// string(50) "A ae Ubermensch pa hoyeste niva! I a lublu PHP! est. fi "

见:http://www.php.net/normalizer

编辑:此解决方案独立于使用 setlocale() 设置的区域设置。 iconv() 的另一个好处是,即使是非拉丁字符也不会被忽略。

EDIT2:我发现,有些字符是我最初发布的音译没有涵盖的。 Any-Latin 将西里尔字符 ь 转换为不适合拉丁字符集的字符:ʹ (http://en.wikipedia.org/wiki/Prime_%28symbol%29)。我添加了[\u0100-\u7fff] remove 来删除所有这些非拉丁字符。我还在文本中添加了一个测试;)

我建议,它们的意思是拉丁字母,而不是 Latin 这里的拉丁字符集之一。但无论如何 - 在我看来,他们应该将其音译为 ASCII 然后在 Latin-ASCII ...

EDIT3:很抱歉这里有另一个变化。我不得不将字符降低到 u0080 而不是 u0100,以仅获取 ASCII 字符作为输出。上面的测试更新了。

【讨论】:

注意:需要启用php_intl.dll扩展 我同意,这对我来说也是最好的功能! (我尝试了很多) 非常好的解决方案,非常易于使用并且比其他使用 str_replace 的解决方案最有用。 应该注意,这不仅会音译文本(如 OP 所要求的那样),还会删除一些字符。例如€(欧元符号)将被删除。只要通过'Any-Latin;拉丁语ASCII;'作为保留这些的第一个参数。或者,您可以使用 iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $str) 将“€”转换为“EUR”。【参考方案2】:

如果你安装了 iconv,试试这个(这个例子假设你的输入字符串是 UTF-8 格式):

echo iconv('UTF-8', 'ASCII//TRANSLIT', $string);

(iconv 是一个用于在各种编码之间进行转换的库;它很高效,并且默认包含在许多 PHP 发行版中。最重要的是,它绝对比尝试推出自己的解决方案更容易且更防错(你知道吗?有一个“带有卷曲的拉丁字母 N”吗?Me neither.))

【讨论】:

+1 打败我。这应该是最好的。但是,请注意,如果输入中有无效字符,这往往会失败(使用ASCII//TRANSLIT//IGNORE 应该会有所帮助)并且通常,如果遇到问题,用户贡献的注释是一个很好的阅读。 php.net/manual/en/function.iconv.php 出于某种原因,有时我无法让它工作。见codepad.viper-7.com/SUufA4 但在另一台机器上,我得到了“`E^au~N”。不过,这不是我们想要的。 这个inconv有一些冲突,所以我会问一个类似的问题 起初这对我不起作用。口音字符刚刚变成?人物。根据 PHP 手册页上对 iconv() 的评论,我首先运行: setlocale(LC_ALL,'en_CA.utf8');然后一切都很完美。 “en_CA.utf8”是我系统上的默认语言环境。尝试“locale -a”查看可用区域列表 这为我解决了问号问题。 setlocale(LC_ALL, "en_US.utf8"); $string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string);【参考方案3】:

应@palantir 的要求重新发布...

我发现 iconv 完全不可靠,我不喜欢 preg_replace 解决方案和大数组......所以我最喜欢的方法(也是我发现的唯一可靠的方法)是......

function toASCII( $str )

    return strtr(utf8_decode($str), 
        utf8_decode(
        'ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ'),
        'SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy');

【讨论】:

您还应该输入以下字母:őŐűŰ。谢谢。 :) 这不是可靠的方法。不适用于像 ŻŹĆŃĄŚŁĘÓżźćńąśłęó 这样的波兰重音字符。试试var_dump(strtr(utf8_decode('qqqqŻŹĆŃĄŚŁĘÓżźćńąśłęóqqq'), utf8_decode('ŻŹĆŃĄŚŁĘÓżźćńąśłęó'),'ZZCNASLEOzzcnasleo')); 我得到了string(25) "qqqqeeeeeeeeOeeeeeeeeoqqq"。 Iconv 更可靠var_dump(iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', 'qqqqŻŹĆŃĄŚŁĘÓżźćńąśłęóqqq')); 我得到string(25) "qqqqZZCNASLEOzzcnasleoqqq" 为我将 'Горловка' 转换为 YYYYYYYY ,不好 在性能方面不是最好的,它也会产生不正确的结果。 Œ、Æ 等字母应分解为两个字母,而不是一个。【参考方案4】:

您可以使用iconv 将字符转译为纯 US-ASCII,然后使用正则表达式删除非字母字符:

preg_replace('/[^a-z]/i', '', iconv("UTF-8", "US-ASCII//TRANSLIT", $text))

另一种方法是使用Normalizer 标准化为Normalization Form KD (NFKD),然后删除标记字符:

preg_replace('/\pMn/u', '', Normalizer::normalize($text, Normalizer::FORM_KD))

【讨论】:

ISO-8859-1?你确定吗?这不会至少留下 ÄÖÜ(作为他们的 8859-1 对应物)吗? 投反对票的原因是什么? 反对票不是我的。但是,OP 并没有要求删除非字母字符,是吗? 这是我的。已修复,现已恢复。 @Pekka:ÈâuÑ 的音译使用iconv 得到`E^au~N。这就是使用以下清理的原因。【参考方案5】:

注意:我从另一个类似的问题重新发布此问题,希望对其他人有所帮助。

我最终基于 Django 项目中的 URLify.js 编写了一个 PHP 库,因为我发现 iconv() 太不完整了。你可以在这里找到它:

https://github.com/jbroadway/urlify

处理拉丁字符以及希腊语、土耳其语、俄语、乌克兰语、捷克语、波兰语和拉脱维亚语。

【讨论】:

本课程适用于我所有基于 iconv 的解决方案对我来说都失败的测试用例。谢谢! 感谢您的这堂课。在 2017 年,该项目仍然存在,并且该类在 PHP7 中完美运行

以上是关于如何去除重音符号并将字母变成“普通”的 ASCII 字符? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

用普通的ascii字符替换重音字符[重复]

查询数据库中包含非重音字母的记录

将非 ASCII 字符(变音符号、重音符号...)转换为最接近的 ASCII 等效字符(创建 slug)

pandas to_csv:ascii 无法编码字符

unicode排序规则,汉字怎么区分大小写,区分重音,区分假名,区分宽度

如何从 .NET 中的字符串中删除变音符号(重音符号)?