我有这个Unicode字符串:Ааа́Ббб́Ввв́Г㥴Дд
我想把它分成字符。
现在,如果我试图循环所有的字符,我会得到这样的东西:
A a a ' Б ...
有没有办法将此字符串正确分割为字符:А а а́
?
答案 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的到来,有新的字符串方法和处理字符串的方法。 有解决方案存在两个问题。
表情符号和其他超出基本多语言平面(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
当你开始使用“字形簇”(一个角色和它的变音符号)时,要解决的难题更难解决。在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
进行管道传输以防止这种情况:
答案 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。