如何确定一系列代码点是否构成一个自然字符?

时间:2012-01-28 17:31:07

标签: java language-agnostic unicode

下午好,

我正在构建一个以字符串作为输入的函数,从字符串中删除任何不自然的组合变音字符,并将修改后的字符串作为输入返回。

非自然组合变音符号序列是一系列unicode代码点,当它们组合在一起时,产生的输出不属于太阳下的任何语言(古代脚本/语言被认为是自然语言)。

例如,给定String输入:

   "aaà̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̯̰̱̲̳̹̺̻̼͇͈͉͍͎́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆͊͋͌̕̚͠͡ͅaa" //code points 0061 0061 0061 0300 0301 0302 0303 0304 0305 0306 0307 0308 0309 030a 030b 030c 030d 030e 030f 0310 0311 0312 0313 0314 0315 0316 0317 0318 0319 031a 031b 031c 031d 031e 031f 0320 0321 0322 0323 0324 0325 0326 0327 0328 0329 032a 032b 032c 032d 032e 032f 032f 0330 0331 0332 0333 0334 0335 0336 0337 0338 0339 033a 033b 033c 033d 033e 033f 0340 0341 0342 0343 0344 0345 0346 0347 0348 0349 034a 034b 034c 034d 034e 0360 0361 0061 0061

,该函数应返回结果aaàaa(代码点0061 0061 0061 0300 0061 0061),

由于à́(代码点0061 0300 0301)不是任何自然语言的字符。换句话说:

  assert F("aaà̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̯̰̱̲̳̹̺̻̼͇͈͉͍͎́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆͊͋͌̕̚͠͡ͅaa").equals("aaàaa");

或者使用拉丁字符集保存的源代码:

 assert F("\u0061\u0061\u0061\u0300\u0301\u0302\u0303\u0304\u0305\u0306\u0307\u0308\u0309\u030a\u030b\u030c\u030d\u030e\u030f\u0310\u0311\u0312\u0313\u0314\u0315\u0316\u0317\u0318\u0319\u031a\u031b\u031c\u031d\u031e\u031f\u0320\u0321\u0322\u0323\u0324\u0325\u0326\u0327\u0328\u0329\u032a\u032b\u032c\u032d\u032e\u032f\u032f\u0330\u0331\u0332\u0333\u0334\u0335\u0336\u0337\u0338\u0339\u033a\u033b\u033c\u033d\u033e\u033f\u0340\u0341\u0342\u0343\u0344\u0345\u0346\u0347\u0348\u0349\u034a\u034b\u034c\u034d\u034e\u0360\u0361\u0061\u0061").equals("\u0061\u0061\u0061\u0300\u0061\u0061");

我们如何确定一系列字符或一系列unicode代码点是否自然

或者更确切地说,属于自然语言的角色会使用多少个变音符号来限制?

3 个答案:

答案 0 :(得分:2)

Unicode 6.0

  

所有组合字符都可以应用于任何基本字符,原则上可以使用   任何脚本。与其他字符一样,将组合字符分配给一个   块或其他只标识其主要用途;它无意定义或限制   可以应用的字符范围。 在Unicode标准中,所有序列   允许使用字符代码。

     

这并不会对实现提供支持所有可能组合的义务   同样好。因此,在将阿拉伯语注释标记应用于汉字时   或者允许使用梵文辅音,在渲染中不太可能得到很好的支持   或者说有意义。

Unicode data中不太可能有足够的信息在算法上执行此操作。

规范composition/decomposition有一些规则可用于确定序列是否为“自然”序列。例如,将U + 0065 U + 0301映射到U + 00E9(é。)但是这不适用于所有情况。

除此之外,我不确定如果不使用由专家构建的某种形式的验证表或者从某些语言数据库生成的验证表,您无法做到。

答案 1 :(得分:1)

我认为你只需要Character.isLetter()。我刚刚用英语,俄语和希伯来语字符进行了尝试,它为所有字母返回true,对所有不是字母的字符返回false。

我不知道'。',','等字符是否自然,但如果需要,你可以轻松枚举所有这些字符。

答案 2 :(得分:1)

  

不自然的组合变音符号序列是一系列unicode代码点,当它们组合在一起时,会产生不属于太阳下任何语言的输出

我担心如果不了解阳光下的所有语言,你将无法满足这一要求。

与标准Unicode数据集最接近的是标准化为NFKC并查看是否还有任何已分解的组合类字符。这并没有告诉你关于自然语言的任何信息,它只依赖于启发式,它可能会为常用的组合定义一个组合字符。这适用于最常见的简单字母表,这对你来说已经足够了。

  

属于自然语言的角色会使用多少个变音符号来限制?

没有。 UAX 15中规定了一个实际限制,即'流安全'文本不得使用30个连续组合字符,这将允许我们推测Unicode标准通常会尝试避免导致该字符定义的字符定义实际语言用例的许多连续加入者。

我所知道的最长的天然字素簇是:

ཧྐྵྨླྺྼྻྂ

(一个初始字符和八个非间距标记。)