如何去除重音符号并将字母变成“普通”的 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 等效字符(创建 slug)