一个关于字符的玄学问题

之前做了一个练习日文听力的网站 因为一些原因做了一下视频数据的迁移。

然后出现了一个玄学问题 明明是同一个url,但是视频却不一定能显示。

// return false   why???? 手动黑人问号
'ヤフーで「のりこえよう」と検索→医療従事者に寄付' ===
'ヤフーで「のりこえよう」と検索→医療従事者に寄付'

你没看错,上面这两段文字显示是一样的,但扔到js里run 返回的是false

很明显,这里面的字符实际上是不同的,使用网上的字符对比工具 可以发现 「で」被高亮了。

然后使用中文转Unicode工具对比发现 第一个是 「\u3067」 而第二个是 「\u3066\u3099」。

这是什么原因呢 我查了下全角半角相关的问题 https://www.yoheim.net/blog.php?q=20191101

有点像是这个问题,但是这个是片假名的处理,而我这边是平假名。这个问题我搞了半天没搞懂,实在不懂这两者的差别是由于什么。

One hours later……

在对比了几个不同的标题后发现了一个规律 这些4字节表现形式都是以 「\u3099」结尾的,然后就Google一下,很幸运,首页一片英文结果中出现了一个看起来相关的中文结果提到了这个关键字。

在 Unicode 中,同一个字符可能有多种不同的编码,比如日语中的浊音符号 \u3099(介绍),
部分假名与这个字符组合可以生成假名的浊化形式,比如 タ(\u30bf) 加上 \u3099 就可以组成 ダ(\u30bf\u3099)。除了 4 字节的表示形式,ダ 还有一种 2 字节的表示形式 \u30c0。这两种模式,前者叫做 NFD,后者叫做 NFC。不仅仅是日语,其他带有浊音或者重音等发音变体形式的语言字符也存在这个问题。

大概是清楚了问题所在了,查找了一下js相关的转换方法。很令人惊讶,这是一个js的内置函数

str = str.normalize('NFD');  //标准转NFD非标准 也就是上面的 「\u3067」-> 「\u3066\u3099」

就这样一行就解决了问题

有趣的是这个提issus的这个项目还是个乃木坂46相关的项目

小声说一句 西野七濑真可爱!

好了,到此这个奇怪的问题也解决了。

要说原因的话,这个issus的作者也提到了

macOS 的 APFS 会将字符按照 NFD 模式显示,但是实际上存储时还是按照我原先下载文件时就设定好的 NFC 模式。然后在生成 pic.json 的时候,歌曲名是 shell 自动生成,再复制进 pic.json 的,因为 shell 显示的就是 NFD 模式,pic.json 自然而然地就也是 NFD 模式,Python 就无法将它与 NFC 模式的歌名匹配上了,cover 就会获取错误。

应该是这个OSS的本地客户端调用shell处理导致的,尚不清楚是不是仅限于MacOS。

然后呢 以后不要在饭前搞事情了 本来6点半打算去吃饭的,一顿操作,然后呢 现在晚上9点半了。算了 也算涨了点冷知识。