Regex - Negative Lookahead 匹配字符串与任何非中文 UTF 字符

Regex - Negative Lookahead to match a string with any non-Chinese UTF characters

意向

创建一个正则表达式,当有任何字符、ASCII、Unicode 或其他字符不属于中文字符的任何有效 UTF-8 范围时,它会创建一个匹配项。匹配本身并不重要,重要的是存在非汉字。请注意,在 UTF-8 字符集中存在罕见且未使用的中文字符也是有意的。函数returns None没有匹配时,表明传入的字符串是纯Unicode中文给调用函数。

代码

Python3.8

chineseRegexSet = "[\u4E00-\u9FFF]|[\u3400-\u4BDF]|[\u20000-\u2A6DF]|[\u2A700-\u2B73F]|[\u2B740-\u2B81F]|[\u2B820-\u2CEAF]|[\uF900-\uFAFF]|[\u2F800-\u2FA1F]"
def ContainsNonChineseCharacters(hanziWord):
    #negative lookahead
    match = search("(?!" + chineseRegexSet + ")+", hanziWord)
    if match:
        if _DEBUG:
            PrintDebugError(hanziWord)
            PrintDebugError(hanziWord, utfEncode=True)
    else:
        _LOGGER.debug(hanziWord)
        if _DEBUG:
            PrintDebug(hanziWord)
            PrintDebug(hanziWord, utfEncode=True)

    return match

尝试正则表达式解决方案

解释:任何非汉字否定。前瞻设置,至少一次

(?![\u4E00-\u9FFF]|[\u3400-\u4BDF]|[\u20000-\u2A6DF]|[\u2A700-\u2B73F]|[\u2B740-\u2B81F]|[\u2B820-\u2CEAF]|[\uF900-\uFAFF]|[\u2F800-\u2FA1F])+

解释: 来自任意UTF集的任意非单数汉字

(?![\u4E00-\u9FFF]+|[\u3400-\u4BDF]+|[\u20000-\u2A6DF]+|[\u2A700-\u2B73F]+|[\u2B740-\u2B81F]+|[\u2B820-\u2CEAF]+|[\uF900-\uFAFF]+|[\u2F800-\u2FA1F]+)*

测试用例

Case 预期结果

大家好 0 个匹配项

00你是谁 >=1 场比赛

s%%2 >=1 场比赛

你Привет >=1 场比赛

感谢您的宝贵时间!

首先,\u20000并不是你想的那样。因为 \u 序列的长度必须正好是 4 位数字,所以这是指 U+2000 和数字 0。对于大于 0xFFFF 的字符,Python 提供 \U,其后必须正好跟 8 个数字(例如 \U00020000)。


其次,

[A-B]|[C-D]|...

最好写成

[A-BC-D...]

通过上述修复和上述简化,我们得到了:

[\u3400-\u4BDF\u4E00-\u9FFF\uF900-\uFAFF\U00020000-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002F800-\U0002FA1F]

有两种方法可以解决这个问题:

  1. 字符串是否只包含 class 中的字符?

    is_just_han = re.search("^[...]*$", str)     # or regex.search
    
  2. 字符串是否包含 class 之外的字符?

    is_just_han = not re.search("[^...]", str)   # or regex.search
    

如果您使用 regex 模块而不是 re 模块,您可以访问 \p{Han}\p{Script=Han} 的缩写)及其否定 \P{Han}\P{Han} 的缩写\P{Script=Han})。此 Unicode 属性 与您要匹配的字符非常匹配。我会让你决定它是否适合你。

is_just_han = regex.search("^\p{Han}*$", str)

is_just_han = regex.search("\P{Han}", str)