如何在 JavaScript 中检测中文字符?

发布日期:2023-09-08 修改时间:2023-09-08 阅读所需:3 分钟
javascript
regular expression

最近在重新复习 TypeScript 的时候打算拿之前基于 Golang 写过的一个 wordcounter 项目用 TypeScript 进行重写,以提高熟练度。

这个项目的核心功能就是对一篇内容中的中文字符进行统计,所以需要一个方法来检测中文字符。由于 Go 提供了良好的 Unicode 支持,可以直接使用 unicode 标准库里的 unicode.Han 字符集来检测中文字符,所以它也就是构成了这个项目的核心算法:

count.go
func (c *TextCounter) Count(input interface{}) error {
str := ""
switch v := input.(type) {
case string:
str = v
case []byte:
str = string(v)
}
if str == "" {
return errors.New("no input provided")
}
scanner := bufio.NewScanner(strings.NewReader(str))
for scanner.Scan() {
c.S.Lines++
line := scanner.Text()
for _, r := range line {
c.S.TotalChars++
if unicode.In(r, unicode.Han) {
c.S.ChineseChars++
} else {
c.S.NonChineseChars++
}
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}

简单来说就是只要某个字符在中文字符集中,那么计数加一。

但在 JavaScript 中这似乎没有提供像 Go 这样标准库可以使用,所以通常如果要匹配中文字符集需要利用 Unicode 的正则表达式来进行匹配,比如:

/[\u4e00-\u9fa5]/.test("中文"); // true

\u4e00\u9fa5 分别是常见中文字符集的开始和结束字符,这个正则表达式通常也适用于其他语言,如 Python。

不过 Unicode 本身提供了对中文汉字的检测方式,即通过指定 Script 属性 来实现:

/\p{Script=Han}/u.test("中文"); // true

它不仅能匹配中文汉字,也能匹配其他 CJK 字符。

所以最终我选定了这种方式来在 TypeScript 版本中实现中文字符的检测:

count.ts
function count(input: string | Uint8Array): Error | null {
let str = "";
if (typeof input === "string") {
str = input;
} else if (input instanceof Uint8Array) {
str = new TextDecoder().decode(input);
}
if (str === "") {
return new Error("No input provided");
}
const lines = str.split("\n");
for (const line of lines) {
this.s.lines++;
for (const char of line) {
this.s.totalChars++;
if (/\p{Script=Han}/u.test(char)) {
this.s.chineseChars++;
} else {
this.s.nonChineseChars++;
}
}
}
return null;
}
}

参考: