如何在Javascript中检查Unicode字符串的相等性?

17

我有两个Javascript字符串:"_strange_chars_µö¬é@zendesk.com.eml"f1)和"_strange_chars_µö¬é@zendesk.com.eml"f2)。乍一看,它们看起来完全相同(在StackOverflow上可能是这样的;我不确定当它们被粘贴到类似这样的表单中时会发生什么)。然而,在我的应用程序中,

f1[16] // ö
f2[16] // o
f1[17] // ¬
f2[17] // ̈

也就是说,当f1使用ö字符时,f2用一个o和一个分音符¨作为单独的字符。我该进行什么比较以展示这两个字符串是“相等”的?


4
也许唯一的解决方案是"规范化"这两个字符串(以Unicode的意义),但我尚未找到可用的库或函数来实现。 - James A. Rosen
1
你确定在你的元标签中声明了UTF-8吗? - cwallenpoole
很好的问题,@cwallenpoole。我不确定,但我现在会再次确认。我描述的这两个字符串肯定都可以是有效的Unicode,但我不确定它们是否真的是。 - James A. Rosen
@cwallenpoole 页面声明了 <meta charset="utf-8">,表单(文件输入是第一个字符串的来源)声明了 accept-charset="UTF-8"。当然,HTTP 请求和响应也是 UTF-8 的。我认为这只是不同系统(浏览器与服务器)使用不同的 Unicode 规范化的情况。(或者使用规范化与否的情况)。 - James A. Rosen
1个回答

8

f1使用ö字符,f2使用o和音符¨作为单独字符。

f1组合型规范(Normal Form C)中,而f2在分解型规范(Normal Form D)中。通常情况下,Windows和Web上最常见的是组合型规范,Unicode FAQ将其描述为“适用于一般文本的最佳形式”。然而,苹果世界不同凡响,选择了分解型规范。

根据Unicode等价性的规则,这两个字符串是等效的。

有什么比较方法可以显示这两个字符串是“相等”的吗?

通常情况下,你将两个字符串转换为你选择的一个规范形式,然后进行比较。例如,在Python中:

>>> import unicodedata
>>> a= u'\u00F6'  # ö composed
>>> b= u'o\u0308' # o then combining umlaut
>>> unicodedata.normalize('NFC', a)==unicodedata.normalize('NFC', b)
True

同样地,Java有Normalizer类,.NET有String.Normalize,很多语言都有ICU库的绑定可用,该库也提供此功能。
不幸的是,JavaScript没有本地Unicode标准化能力。这意味着要么自己动手,在JavaScript中携带大型Unicode数据表来覆盖它所有内容(例如,在此处查看示例实现);要么将其发送回服务器端(例如,通过XMLHttpRequest),在那里使用更强大的语言来处理它。

1
你关于苹果的说法是不真诚的不实之词。苹果的HSF+文件系统出于完全合理的原因使用(曾经的)NFD。预组合字符被Unicode视为与遗留编码往返兼容性字符,并且不是您在此处错误陈述的内部使用首选形式。标准建议是在您处理数据之前的第一步将所有传入数据NFD,然后在您分手之前的最后一步将所有传出数据NFC。单例因此发生变异,但这种情况终究会发生。 - tchrist
1
@tchrist:关于复合字符被称为“兼容性”的引用?它们肯定不是字面上的兼容性,因为毕竟有正常形式KC。官方[FAQ](http://www.unicode.org/faq/normalization.html)更喜欢NFC / NFKC,并仅提到分解在内部处理中有用。但是,在HFS +和UFS上的文件名不仅仅是内部的数据,这些数据返回应用程序,这使得许多应用程序崩溃。 OS X文件系统未将文件名回归到NFC,就像您建议应该做的那样。 - bobince
个人认为,文件系统中的大小写不敏感和组合不敏感都是不可取的特性,但至少在Windows的情况下,您会得到最初输入的大小写。 - bobince
JS现在已经有这个功能了 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize。不幸的是,IE11不支持此功能,虽然您可以使用外部库,例如https://github.com/walling/unorm,但它对于前端使用来说太庞大了。 - Yi Jiang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接