代码、游戏、以及有趣的故事
2023-03-22
总所周知因为中文是一种表意文字,其字符数量庞大,有不少计算机系统都不能完整的展示中文字符;中文的字体和排版也比英文复杂。中文的字体种类繁多,不同的字体在显示效果和占用空间上可能会有所不同。此外,中文的排版需要考虑字间距、行间距、对齐方式等因素,以保证文字的可读性和美观性。 而在国内开发有时候必须限制用户进行中文输入,比如用户中文名、中文密码、聊天等等;这些功能在遇上中文那数万之多的字符个数都是非常难以处理的。
在 Javascript 中最好的处理方式当然是使用正则表达式去获取;
适用于大多数场景的:
function isChinese(str) {
const re = /^[\u4e00-\u9fa5]+$/;
return re.test(str);
}
但需要注意的是,中文汉字的数量是非常庞大的(具体数量不详,但基本超过了十万),而上面代码涵盖只涵盖了大约不到三万个汉字;虽然已经满足大家日常交流的使用需求。但是在部分特殊情况下使用可能就很难满足了(比如很多人就喜欢使用生僻的汉字来作为昵称或用户名)。
如果只是想粗暴的匹配汉字,那使用下面代码也是可以的:
function isChinese(str) {
const re = /^[\u4e00-\u9fa5]+$/;
return re.test(str);
}
注意,这种方式是非常粗暴的,其会误伤很多符号,如逗号和句号等等。
更精准的捕获汉字:
function isChinese(str) {
const re = /[\u4E00-\u9FFF\u3400-\u4DBF\uF900-\uFAFF\U00020000-U0002EBEF]/;
return re.test(str);
}
这个是直接按照 Unicode 的中文字符对照表编写的正则;需要注意的是,由于各个操作系统、软件对 Unicode 的支持不完全相同,所以上面的代码有时也会造成误伤其他字符比如说数字。
Java 的处理方式当然也可以是使用正则表达式了,具体使用方式和 JavaScript 中的基本差多的,Java中涉及正则处理的包是: java.util.regex 。
Java 中还有一种比较有趣的处理方式,那就是使用 java.lang 包下的 Character.UnicodeBlock ,来处理汉字识别;
关于 Character.UnicodeBlock 官方的介绍是:一系列字符子集,表示Unicode规范中的字符块。 字符块通常定义用于特定脚本或目的的字符。 字符最多包含一个Unicode块。
public static boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
return true;
}
return false;
}
主要是利用 Unicode 编码中的 CJK 编码区间(统一汉字编码)来进行处理。
GO 同样也是可以用正则处理的,使用 regexp 即可。但 Go 其实有更加优雅的处理方式:
for _, r := range str {
if unicode.Is(unicode.Scripts["Han"], r) {
return true
}
}
return false
Go 内置了对汉字 unicode 编码的处理集,且这个处理集对绝大多数汉字都有兼容,实际使用时,只需要通过正则再额外匹配几个符号就可以了。个人认为算是非常的优雅了。