【问题标题】:Different UTF-8 signature for same diacritics (umlauts) - 2 binary ways to write umlauts相同变音符号(变音符号)的不同 UTF-8 签名 - 2 种二进制方式来编写变音符号
【发布时间】:2012-08-27 18:24:02
【问题描述】:

我有一个很大的问题,我在网上找不到任何帮助:

我将一个页面从一个网站从 OSX 移动到 Linux(两个系统都在 de_DE.UTF-8 中运行)并在一个完全未知的问题中运行: 一些文件不再被发现,但显然存在于硬盘驱动器上(明显)同名。所有这些文件都包含德语变音符号。

我拿了一张样本图片,从网页上复制了原始的 request-uri 并直接调用它——同样的错误。重写文件名后它起作用了。是的,我没有打错!

这让我很吃惊,我查看了 apache-log,在其中发现了这些条目:

192.168.56.10 - - [27/Aug/2012:20:03:21 +0200] "GET /images/Sch%C3%B6ne-Lau-150x150.jpg HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.1"
192.168.56.10 - - [27/Aug/2012:20:03:57 +0200] "GET /images/Scho%CC%88ne-Lau-150x150.jpg HTTP/1.1" 404 4205 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.1"

这是我要调查的事情...这是我在 UTF8 图表 http://www.utf8-chartable.de/ 中找到的内容:

ö   c3 b6   LATIN SMALL LETTER O WITH DIAERESIS
¨   cc 88   COMBINING DIAERESIS

我想你已经听说过死键:http://en.wikipedia.org/wiki/Dead_key 如果没有,请阅读文章。这很有趣;)

这是否意味着 OSX 将所有变音符号与字母分开保存?这是否真的意味着 OSX 将字符 ö 保存为 o 和 ¨ 而不是使用组合产生的真实字符?

如果是,你知道我可以用来重命名这些文件的好脚本吗?这不会是我从 OSX 迁移到 Linux 的第一页...

【问题讨论】:

标签: linux macos utf-8 diacritics dead-key


【解决方案1】:

它与死键不太一样,但它是相关的。如您所见,U+00F6 和 U+006F 后跟 U+0308 具有相同的视觉效果。

实际上有 Unicode 规则知道如何对待它们,这是基于分解的。字符数据库中有一个分解表,它告诉我们 U+00F6 规范地分解为 U+006F,然后是 U+0308。

除了规范分解之外,还有兼容性分解。这些会丢失一些信息,例如² 最终被分解为2。这显然是一个破坏性的更改,但是当您想要有点模糊时,它对于搜索很有用(google 如何知道搜索 fiſh 应该返回关于鱼的结果)。

如果在一个非组合字符之后有多个组合字符,那么我们可以重新排序它们只要我们不重新排序同一类的那些。当我们考虑到我们是否在某物上放一个 cedilla 然后是一个尖锐的重音,或者一个尖锐然后是一个 cedilla 并不重要时,这一点变得很清楚,但是如果我们在一个字母上同时放一个尖锐和变音符号,那么显然很重要他们走的路。

由此,我们有 4 种规范化形式。在进行比较之前将字符串放入适当的规范化形式中,您就不会被绊倒。

NFD:通过尽可能地规范地分解所有内容。按照组合类的顺序重新排列组合字符,但保持任何具有相同类的相对于彼此的顺序相同。

NFC:首先将所有内容放入 NFD。然后继续按顺序查看组合字符,如果没有同一类的较早一个。如果有等效的单个字符,则替换它们,然后重新扫描以进一步组合。

NFKD:与 NFD 类似,但使用兼容性分解(破坏性更改,但对比较有用,如上所述)。

NFD:执行 NFKD,然后仅根据 NFC 重新组合规范

还有一些重组禁止在 NFC 中使用,因此如果 Unicode 添加了更多字符,则在一个 Unicode 版本中有效 NFC 的文本不会不再是 NFC。

在 NFD 和 NFC 中,NFC 显然更为简洁。它可能不是最简洁的,但它非常简洁,可以通过非常有效的流式传输方式进行测试和/或创建。

Mac OSX 使用 NFD 作为文件名。因为他们是怪人。 (好吧,还有比这更好的论据,只是没有说服我!)

网络角色模型使用 NFC。*因此,您应该尽可能在网络内容上使用 NFC。盲目地将东西转换为 NFC 可能存在安全考虑。但如果它从你开始,它应该从 NFC 开始。

任何处理文本的编程语言都应该有一种将文本规范化为任何这些形式的好方法。如果你的没有抱怨(或者如果你的是开源的,那就贡献吧!)。

请参阅http://unicode.org/faq/normalization.html 了解更多信息,或http://unicode.org/reports/tr15/ 了解完整的详细信息。

*为了更有趣,如果您在 XML 或 HTML 元素内容的开头插入了以组合长实线覆盖 (U+0338) 开头的内容,它会将标签的 > 转换为 ,将格式良好的 XML 变成乱码。出于这个原因,网络字符模型坚持每个实体本身必须是 NFC,并且不能以组合字符开头。

【讨论】:

  • 反对怪异的东西:这张表说,要求不是因为操作系统,而是因为文件系统 HFS+ developer.apple.com/library/mac/#qa/qa1173/_index.html
  • @SimonSimCity 仍然不相信这是 HFS+ 应该采取的路线,但添加的很好的链接可以反驳我对它的半开玩笑的描述。
【解决方案2】:

感谢 Jon Hanna 在这里提供了许多背景信息!这对于获得完整答案很重要:一种从一种规范化形式转换为另一种规范化形式的方法。

由于我的更改位于数据库中链接的文件系统中(由于文件上传),我现在必须更新我的数据库转储。文件在移动过程中已经被重命名(可能由 FTP 客户端 ...)

在 Linux 上转换字符集的命令行工具有:

  • iconv - 转换流的内容(可能是文件)
  • convmv - 转换目录中的文件名

我可以在 iconv 中使用的字符集 utf-8-mac(如 http://loopkid.net/articles/2011/03/19/groking-hfs-character-encoding 中所述)似乎只存在于 OSX 系统上,所以我必须将我的 sql-dump 移动到我的 mac,转换它并移动回来了。另一种选择是使用 convmv 将文件重命名为 NFD,但我认为这对未来的帮助大于帮助。

convmv 工具有一个内置(独立于操作系统)选项来强制使用与 NFC 或 NFD 兼容的文件名:http://www.j3e.de/linux/convmv/man/

PHP 本身(我的系统 - Wordpress 所基于的语言)在这里支持兼容性层: In PHP, how do I deal with the difference in encoded filenames on HFS+ vs. elsewhere? 在我为我解决了这个问题之后,我会去写一些测试,也可能会写一个错误报告给 Wordpress 和我使用的其他系统;)

【讨论】:

  • 作为最近开始大量使用 Linux 的人,我也从这个问题中学到了一些东西。每个人都是赢家:)
【解决方案3】:

Linux 发行版将文件名视为二进制字符串,这意味着不假设编码 - 尽管图形外壳(Gnome、KDE ​​等)可能会根据环境变量、语言环境等做出一些假设。

另一方面,OS-X 要求或强制(我忘记了)他们自己的带有 Unicode 规范化的 UTF-8 版本,以将所有变音符号扩展为组合字符。

在 Linux 上,当人们确实在文件名中使用 Unicode 时,他们倾向于使用带有预组合字符的 UTF-8 来处理变音符号。

【讨论】:

    猜你喜欢
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    相关资源
    最近更新 更多