JavaScript 打印所有使用过的 Unicode 字符

6

我正在尝试使JavaScript打印出所有Unicode字符。根据我的研究,Unicode字符的数量为1,114,112个。

以下这样的脚本可能有效:

for(i = 0; i < 1114112; i++) 
    console.log(String.fromCharCode(i));

然而,我发现只有1114112个Unicode字符中的10%被使用。

我该如何仅打印已使用的Unicode字符?


1
你所说的“used characters”是什么意思? - Anthony Raymond
1
请注意,JavaScript 字符串采用 UTF-16 编码,因此您需要处理代理对。此外,每个字符的显示还取决于所使用的字体以及是否为代码点定义了字形。如果您想确定字体支持哪些代码点,则在大多数 JavaScript 环境中通常无法获得该信息。 - Jonathan Lonowski
正如我在问题中所说,“只有1114112个Unicode字符的10%被使用”。@AnthonyRaymond - Progo
@Progo:那么“used”是什么意思? - Thanatos
@Thanatos 由于只有1,114,112个Unicode字符中的10%被使用,其余部分未被使用并保留供将来使用。 - Progo
啊,"分配的代码点"。 - Thanatos
3个回答

7

正如Jukka所说的那样, JavaScript没有内置的方法来判断一个给定的Unicode码点是否已经被分配了符号。

不过,还是有办法实现你想要的功能。

我编写了几个 脚本来解析Unicode数据库,并为每个类别、属性、脚本、块等创建单独的数据文件。我还创建了一个HTTP API,允许您以编程方式获取给定Unicode类别中的所有代码点(即数字数组),或具有给定Unicode属性的所有符号(即每个字符的字符串数组),或匹配某个Unicode脚本中的任何符号的正则表达式。

例如,要获取一个包含每个已分配Unicode v6.3.0中的符号的Unicode码点的字符串数组,您可以使用以下URL:

http://mathias.html5.org/data/unicode/format?version=6.3.0&property=Assigned&type=symbols&prepend=window.symbols%20%3D%20&append=%3B

请注意,您可以通过调整URL参数在输出前缀和后缀添加任何内容,以便更轻松地重用数据。 例如,按照您的要求,将console.log()所有这些符号的示例HTML页面编写如下:
<!DOCTYPE html>
<meta charset="utf-8">
<title>All assigned Unicode v6.3.0 symbols</title>
<script src="http://mathias.html5.org/data/unicode/format?version=6.3.0&property=Assigned&type=symbols&prepend=window.symbols%20%3D%20&append=%3B"></script>
<script>
  window.symbols.forEach(function(symbol) {
    // Do what you want to do with `symbol` here, e.g.
    console.log(symbol);
  });
</script>

演示。请注意,由于数据量很大,打开此页面时您的DevTools控制台可能会变得缓慢。


更新:现在,你应该使用Unicode数据包,例如unicode-11.0.0。在Node.js中,你可以执行以下操作:

const symbols = require('unicode-11.0.0/Binary_Property/Assigned/symbols.js');
console.log(symbols);

// Or, to get the code points:
require('unicode-11.0.0/Binary_Property/Assigned/code-points.js');

// Or, to get a regular expression that only matches these characters:
require('unicode-11.0.0/Binary_Property/Assigned/regex.js');

这些工具看起来很有趣,但是文档很令人困惑。总之,你的演示列出了249,703个代码点,这太多了。根据官方Unicode 6.3信息:“此次增加将标准中分配的字符总数增加到110,122个。(这是传统计数方法,将图形和格式字符合计,但不包括代理代码点、ISO控制码、非字符和专用分配。)” - Jukka K. Korpela
1
我期望标准中提到的数字是110,122。看起来你的代码不仅包括ISO控制码(可能被称为“控制字符”,但这个说法有争议),还包括私用代码点(标准明确未分配任何字符)和代理项(根本不是Unicode字符)。 - Jukka K. Korpela
@JukkaK.Korpela TR18 表示:“Assigned 等同于 \P{Cn},匹配所有已分配的字符(针对 Unicode 的目标版本)。它还包括所有私用字符。它有助于避免混淆的双重否定。请注意,Cn 包括非字符,因此 Assigned 不包括它们。” 基于这个,似乎输出是正确的 — 你同意吗? - Mathias Bynens
自己注意:关于“非字符”的定义,请参见Unicode标准第16.7节。按照该定义,输出中似乎没有包含任何非字符。我也没有看到任何私有使用代码点。http://mathias.html5.org/data/unicode/format?version=6.3.0&property=Assigned&type=code-points&prepend=window.codePoints%20%3D%20&append=%3B中是否还包含其他内容? - Mathias Bynens
1
请将演示链接改为https,因为http无法工作。控制台中出现了混合内容错误。 - Alfred
显示剩余5条评论

1
在JavaScript中,没有直接的方法可以找出一个代码点是否被赋予了一个字符,这似乎是这里的问题。您需要从合适的来源提取信息,并且这些信息需要在新版Unicode中分配新字符时进行更新。
Unicode中有1,114,112个代码点。 Unicode标准为每个代码点分配属性gc,通用类别。如果此属性的值不是Cs、Co或Cn,则将代码点分配给字符。(具有gc等于Co的代码点是私用代码点,它们没有分配字符,但它们可以通过私人协议用于字符。)
您需要做的是获取Unicode字符数据库中一些相关文件的副本(实际上只是特定格式的文件集合),并编写读取它并生成有关已分配代码点的信息的代码。为了打印所有Unicode字符,最好将信息生成为已分配代码点范围的数组。当标准使用新字符更新时,需要重复执行此操作。
即使是其余部分也不是琐碎的。您需要决定打印字符的含义。一些字符是控制字符,可能会产生影响,例如导致换行,但缺少可见字形。一些(空格)具有空字形。一些(组合标记)旨在呈现为附加到前面字符的标记,尽管它们也有“独立”字符的惯用呈现方式。一些字符根据最近的上下文而意味着基本上不同的形状;它们也可能有孤立形式,但仅仅写一个字符并不保证使用孤立形式。
然后是字体问题。没有单一的字体可以包含所有Unicode字符,因此您需要找到一组字体,当它们一起使用时,涵盖所有Unicode,最好以某种方式风格匹配。
因此,如果您只是在寻找所有可打印的Unicode字符的编译,请考虑使用Unicode代码图表

这篇文章中的所有内容都是绝对正确的,但它并没有真正回答问题。以下是 OP 可以实现他们想要的方式:https://dev59.com/wH7aa4cB1Zd3GeqPminO#22755675 - Mathias Bynens

0

这里的问题是,与普遍观点相反,JavaScript并不是Unicode环境。

在内部,它使用USC-2,这是一种不兼容的16位编码方法,早于UTF16。

此外,许多Unicode字符本身不能直接打印——其中一些是前面字符的修改——例如,西班牙字母ñ可以用Unicode写成单个点(该字符)或两个点(n~)。

以下是几个资源,应该真正帮助您理解这一点:


这并没有回答问题。 - Jukka K. Korpela
@JukkaK.Korpela,这确实有帮助,因为OP建议使用String.fromCharCode对于星际符号不起作用。 - Mathias Bynens

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