带字符串的Unicode字符串由字符分隔

时间:2012-05-25 17:31:40

标签: javascript string unicode split char

我有这个Unicode字符串:Ааа́Ббб́Ввв́Г㥴Дд

我想把它分成字符。 现在,如果我试图循环所有的字符,我会得到这样的东西:
 A a a ' Б ...

有没有办法将此字符串正确分割为字符:А а а́

5 个答案:

答案 0 :(得分:8)

为了正确地做到这一点,你想要的是用于计算字形空间簇边界的算法,如UAX 29中所定义的。不幸的是,这需要知道哪些字符是哪些类的成员,从Unicode字符数据库和JavaScript不能提供该信息(*)。所以你必须在你的脚本中加入UCD的副本,这会使它变得相当笨重。

另一种选择,如果你只需要担心拉丁语或西里尔语使用的基本口音,那就是只采用组合变音符号块(U + 0300-U + 036F)。对于其他语言和符号,这将失败,但可能足以满足您的目的。

function findGraphemesNotVeryWell(s) {
    var re= /.[\u0300-\u036F]*/g;
    var match, matches= [];
    while (match= re.exec(s))
        matches.push(match[0]);
    return matches;
}

findGraphemesNotVeryWell('Ааа́Ббб́Ввв́Г㥴Дд');
["А", "а", "а́", "Б", "б", "б́", "В", "в", "в́", "Г", "г", "Ґ", "ґ", "Д", "д"]

(*:可能是一种通过让浏览器呈现字符串来提取信息的方法,并测量其中的选择位置...但它肯定会非常混乱和困难让跨浏览器工作。)

答案 1 :(得分:7)

此软件包可能对您有所帮助: https://www.npmjs.com/package/runes

const runes = require('runes')

const example = 'Emoji '
example.split('') // ["E", "m", "o", "j", "i", " ", "�", "�"] 
runes(example)    // ["E", "m", "o", "j", "i", " ", ""] 

答案 2 :(得分:4)

对此有点了解。

随着ES6的到来,有新的字符串方法和处理字符串的方法。 有解决方案存在两个问题。

1)表情符号和代理对

表情符号和其他超出基本多语言平面(BMP)的Unicode字符(0x0000 - 0xFFFF范围内的Unicode“代码点”)可以作为ES6 adhere to the iterator protocol中的字符串计算出来,所以你可以这样做:

let textWithEmoji = '\ud83d\udc0e\ud83d\udc71\u2764'; //horse, happy face and heart
[...textWithEmoji].length //3
for (char of textWithEmoji) { console.log(char) } //will log 3 chars

2)变音符号

当你开始使用“字形簇”(一个角色和它的变音符号)时,要解决的难题更难解决。在ES6中有一种简化工作的方法,但它仍然很难工作。 String.prototype.normalize方法简化了工作,但正如Mathias Bynens一样:

  

(A)应用了多个组合标记的代码点总是会生成一个可视字形,但可能没有标准化形式,在这种情况下,规范化无效。

可以在此处找到更多见解:

https://ponyfoo.com/articles/es6-strings-and-unicode-in-depth https://mathiasbynens.be/notes/javascript-unicode

答案 3 :(得分:0)

如果您编写的应用程序需要使用Node.js stream中的大量数据,则可以通过utf8-stream进行管道传输以防止这种情况:

https://github.com/substack/utf8-stream

答案 4 :(得分:-1)

你的字符串的问题是surogate对(“a”“)只有在浏览器显示时才能组合才能发出信号。对于你的情况,如果你将\ u0301附加到前一个字符就足够了但这是不是一般解决方案。

var a="Ааа́Ббб́Ввв́Г㥴Дд",
    i =0,
    chars=[];

while(a.charAt(i)) {
  if (a.charAt(i+1) == "\u0301") {
    chars.push(a.charAt(i++)+a.charAt(i++));
  } else {
    chars.push(a.charAt(i++));}}

要澄清此问题,请阅读Mathias Bynens's blog post