我正在尝试使用javascript删除unicode字符串。所述字符串可以计算混合字符。示例:我的中文不好。我是意大利人。你知道吗?
最终,字符串可能包含 - 中国文字 - 中文标点符号 - ANSI字符和标点符号
我只需留下汉字。任何提示?
答案 0 :(得分:25)
您可以在http://www.unicode.org/reports/tr38/#BlockListing或http://www.unicode.org/charts/看到相关的阻止。
如果您要排除兼容性字符(不应再使用的字符),以及笔画,部首和封闭的CJK字母和月份,则应覆盖以下内容(之后我添加了单独的JavaScript等效表达式) ):
[\u4E00-\u9FCC]
[\u3400-\u4DB5]
[\ud840-\ud868][\udc00-\udfff]|\ud869[\udc00-\uded6]
\ud869[\udf00-\udfff]|[\ud86a-\ud86c][\udc00-\udfff]|\ud86d[\udc00-\udf34]
\ud86d[\udf40-\udfff]|\ud86e[\udc00-\udc1d]
[\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]
...所以,抓住汉字的正则表达式是:
/[\u4E00-\u9FCC\u3400-\u4DB5\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\ud840-\ud868][\udc00-\udfff]|\ud869[\udc00-\uded6\udf00-\udfff]|[\ud86a-\ud86c][\udc00-\udfff]|\ud86d[\udc00-\udf34\udf40-\udfff]|\ud86e[\udc00-\udc1d]/
事实上,由于许多CJK(中日韩)字符,Unicode被扩展为处理“基本多语言平面”之外的更多字符(称为“星体”字符),并且因为CJK统一表意文字扩展BD是这些星体字符的例子,这些扩展的范围更复杂,因为它们必须使用UTF-16系统(如JavaScript)中的代理对进行编码。代理对由高代理和低代理组成,它们本身都不是有效的,但是当它们连接在一起形成一个实际的单个字符,尽管它们的字符串长度为2)。
虽然替换目的可能更容易将其表示为非中文字符(用空字符串替换它们),但我提供了中文字符的表达式,以便在以下情况下更容易跟踪你需要在块中添加或删除。
2017年9月更新
从ES6开始,人们可以通过使用“u”标志以及带有括号的新转义序列内部的代码点来表达正则表达式而不诉诸代理,例如,/^[\u{20000}-\u{2A6D6}]*$/u
用于“CJK统一表意文字扩展B“。
请注意,Unicode也已经发展到包括“CJK Unified Ideographs Extension E”([\u{2B820}-\u{2CEAF}]
)和“CJK Unified Ideographs Extension F”([\u{2CEB0}-\u{2EBEF}]
)。
对于ES2018,似乎Unicode属性转义将能够进一步简化。每http://2ality.com/2017/07/regexp-unicode-property-escapes.html,它看起来能够做到:
/^(\p{Block=CJK Unified Ideographs}|\p{Block=CJK Unified Ideographs Extension A}|\p{Block=CJK Unified Ideographs Extension B}|\p{Block=CJK Unified Ideographs Extension C}|\p{Block=CJK Unified Ideographs Extension D}|\p{Block=CJK Unified Ideographs Extension E}|\p{Block=CJK Unified Ideographs Extension F}|[\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29])+$/u
由于来自http://unicode.org/Public/UNIDATA/PropertyAliases.txt和http://unicode.org/Public/UNIDATA/PropertyValueAliases.txt的较短别名也可用于这些块,您可以将其缩短为以下(如果需要,还可以将下划线更改为空格或套管):
/^(\p{Blk=CJK}|\p{Blk=CJK_Ext_A}|\p{Blk=CJK_Ext_B}|\p{Blk=CJK_Ext_C}|\p{Blk=CJK_Ext_D}|\p{Blk=CJK_Ext_E}|\p{Blk=CJK_Ext_F}|[\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29])+$/u
如果我们想提高可读性,我们可以使用命名捕获组来记录错误标记的兼容性字符(请参阅http://2ality.com/2017/05/regexp-named-capture-groups.html):
/^(\p{Blk=CJK}|\p{Blk=CJK_Ext_A}|\p{Blk=CJK_Ext_B}|\p{Blk=CJK_Ext_C}|\p{Blk=CJK_Ext_D}|\p{Blk=CJK_Ext_E}|\p{Blk=CJK_Ext_F}|(?<CJKFalseCompatibilityUnifieds>[\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]))+$/u
因为它看起来像{Unified_Ideograph'属性(别名“UIdeo”)所涵盖的所有统一表意符号并且不包括符号/标点符号和兼容性字符,如果您不需要选择除此之外,您可能只需要以下内容:
/^\p{Unified_Ideograph=yes}*$/u
或简写:
/^\p{UIdeo=y}*$/u
答案 1 :(得分:5)
从Chrome 64, Firefox 79, and Safari 11.1开始,用于测试字符串是否为汉字的最简单的正则表达式为/\p{Script=Han}/u
。 \p{}
指定一个Unicode property escape,Script=Han
表达式匹配其script
属性为Han
(中文)的任何字符,以及u
{{ 3}}允许在正则表达式中使用Unicode功能,例如这些属性转义符。
因此,您可以像这样在字符串中过滤掉中文字符:
console.log(
"hello! 42 我的中文不好。我是意大利人。你知道吗?"
.split("")
.filter(char => /\p{Script=Han}/u.test(char))
.join("")
);
Script
属性名称也可以缩写,例如/\p{sc=Han}/u
。
答案 2 :(得分:2)
没有捷径。您必须构造一个表达式,其中包含您要保留的字符类或要删除的字符类,然后处理它。
Unicode联盟为标准定义的各种范围提供代码图表(index)(如this PDF of CJK Symbols and Punctuation)。因为它们经常有很长的连续代码点,所以你可以相对容易地将它们放在一个字符类中。
答案 3 :(得分:0)
而不是发明自己的解决方案,你可以使用unicode-data模块(确切地说是由它生成的模块之一),这实际上是UnicodeData.txt database的javascript接口(类似于unicodedata标准) python中的模块,如果它响铃了。)
答案 4 :(得分:0)
复制粘贴解决方案。使用ES6的unicode标志。所有当前的扩展程序,直到扩展程序F和表意文字。
const character_xp = new RegExp(String.raw`
[\u{FA0E}\u{FA0F}\u{FA11}\u{FA13}\u{FA14}\u{FA1F}\u{FA21}\u{FA23}\u{FA24}\u{FA27}-\u{FA29}]
|[\u{4E00}-\u{9FCC}]
|[\u{3400}-\u{4DB5}]
|[\u{20000}-\u{2A6D6}]
|[\u{2A700}-\u{2B734}]
|[\u{2B740}-\u{2B81D}]
|[\u{2B820}-\u{2CEAF}]
|[\u{2CEB0}-\u{2EBEF}]
`.replace(/\s+/g, ''), "u")