使用Python和正则表达式查找字符串中的所有中文文本

28

今天我需要从一堆字符串中去掉中文,并寻找一个简单的 Python 正则表达式。有什么建议吗?


你确定要删除中文吗?还是你真的想删除所有非拉丁字符? - SingleNegationElimination
1
为什么需要(或有用)从字符串中删除中文字符而不是翻译它们呢? - Anderson Green
2个回答

51

Python 2:

#!/usr/bin/env python
# -*- encoding: utf8 -*-


import re

sample = u'I am from 美国。We should be friends. 朋友。'
for n in re.findall(ur'[\u4e00-\u9fff]+',sample):
    print n

Python 3

sample = 'I am from 美国。We should be friends. 朋友。'
for n in re.findall(r'[\u4e00-\u9fff]+', sample):
    print(n)

输出:

美国
朋友

关于Unicode代码块

4E00—9FFF 范围包含CJK统一表意文字(CJK=中文、日文和韩文)。还有一些较低的范围,与CJK略有关联:

31C0—31EF CJK Strokes
31F0—31FF Katakana Phonetic Extensions
3200—32FF Enclosed CJK Letters and Months
3300—33FF CJK Compatibility
3400—4DBF CJK Unified Ideographs Extension A
4DC0—4DFF Yijing Hexagram Symbols
4E00—9FFF CJK Unified Ideographs 

这不适用于所有的中文字符,因为有些是代理对当 UTF-16 编码。(由于您正在使用 \u4e00 和 \u9fff,看起来像是 UTF-16) - Stephen Nutt
@Stephen:这是真的,但BMP之外的中文字符大多是不用于现代汉字书写的变体/历史形式,所以这很可能无关紧要。Prairiedogg可能不关心的其他潜在问题:正如您在上面的示例中看到的那样,该代码正在提取汉字,但忽略了中文标点符号;它还将忽略各种其他中文符号(圆形字符等);并且对日语文本会产生奇怪和可怕的影响。 - Porculus
实际上,当我处理我的数据集时,我认为TokenMacGuy是正确的 - 我真的想剥离所有非拉丁字符。 - prairiedogg

35
对于狭窄的Python Unicode版本(不包括ordinal> 65535,这些只能通过代理对在狭窄的Unicode版本中表示),简短但相对全面的答案是:
RE = re.compile(u'[⺀-⺙⺛-⻳⼀-⿕々〇〡-〩〸-〺〻㐀-䶵一-鿃豈-鶴侮-頻並-龎]', re.UNICODE)
nochinese = RE.sub('', mystring)

构建RE的代码,如果你需要在宽字符中检测中文字符,可以使用补充平面

# -*- coding: utf-8 -*-
import re

LHan = [[0x2E80, 0x2E99],    # Han # So  [26] CJK RADICAL REPEAT, CJK RADICAL RAP
        [0x2E9B, 0x2EF3],    # Han # So  [89] CJK RADICAL CHOKE, CJK RADICAL C-SIMPLIFIED TURTLE
        [0x2F00, 0x2FD5],    # Han # So [214] KANGXI RADICAL ONE, KANGXI RADICAL FLUTE
        0x3005,              # Han # Lm       IDEOGRAPHIC ITERATION MARK
        0x3007,              # Han # Nl       IDEOGRAPHIC NUMBER ZERO
        [0x3021, 0x3029],    # Han # Nl   [9] HANGZHOU NUMERAL ONE, HANGZHOU NUMERAL NINE
        [0x3038, 0x303A],    # Han # Nl   [3] HANGZHOU NUMERAL TEN, HANGZHOU NUMERAL THIRTY
        0x303B,              # Han # Lm       VERTICAL IDEOGRAPHIC ITERATION MARK
        [0x3400, 0x4DB5],    # Han # Lo [6582] CJK UNIFIED IDEOGRAPH-3400, CJK UNIFIED IDEOGRAPH-4DB5
        [0x4E00, 0x9FC3],    # Han # Lo [20932] CJK UNIFIED IDEOGRAPH-4E00, CJK UNIFIED IDEOGRAPH-9FC3
        [0xF900, 0xFA2D],    # Han # Lo [302] CJK COMPATIBILITY IDEOGRAPH-F900, CJK COMPATIBILITY IDEOGRAPH-FA2D
        [0xFA30, 0xFA6A],    # Han # Lo  [59] CJK COMPATIBILITY IDEOGRAPH-FA30, CJK COMPATIBILITY IDEOGRAPH-FA6A
        [0xFA70, 0xFAD9],    # Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70, CJK COMPATIBILITY IDEOGRAPH-FAD9
        [0x20000, 0x2A6D6],  # Han # Lo [42711] CJK UNIFIED IDEOGRAPH-20000, CJK UNIFIED IDEOGRAPH-2A6D6
        [0x2F800, 0x2FA1D]]  # Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800, CJK COMPATIBILITY IDEOGRAPH-2FA1D

def build_re():
    L = []
    for i in LHan:
        if isinstance(i, list):
            f, t = i
            try: 
                f = unichr(f)
                t = unichr(t)
                L.append('%s-%s' % (f, t))
            except: 
                pass # A narrow python build, so can't use chars > 65535 without surrogate pairs!

        else:
            try:
                L.append(unichr(i))
            except:
                pass

    RE = '[%s]' % ''.join(L)
    print 'RE:', RE.encode('utf-8')
    return re.compile(RE, re.UNICODE)

RE = build_re()
print RE.sub('', u'美国').encode('utf-8')
print RE.sub('', u'blah').encode('utf-8')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接