如何使用Unicode正则表达式范围替换字符

时间:2018-11-27 21:32:58

标签: python regex string unicode range

我正在尝试从Unicode字符串中删除字符。我有一个允许的Unicode字符白名单,我想删除列表中没有的所有内容。

    allowed_list = ur'[\u0041-\u005A]|[\u0061-\u007A]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u012F]|\u0131|[\u0386]|[\u0388-\u038A]'
    negated_list = ur'[^\u0041-\u005A]|[^\u0061-\u007A]|[^\u00C0-\u00D6]|[^\u00D8-\u00F6]|[^\u00F8-\u012F]|^\u0131|[^\u0386]|[^\u0388-\u038A]'

我正在用列表的一个子集对其进行测试,但我不知道为什么它不起作用。

这会删除所有小写的拉丁字符:

    >>> mystr = 'Arugg^]T'
    >>> myre = re.compile(ur'[^\u0061-\u007A]', re.UNICODE)
    >>> result = myre.sub('', mystr)
    >>> result
    'rugg'

这会删除所有大写拉丁字符:

    >>> mystr = 'Arugg^]T'
    >>> myre = re.compile(ur'[^\u0041-\u005A]', re.UNICODE)
    >>> result = myre.sub('', mystr)
    >>> result
    'AT'

但是当我将它们组合时,所有字符都将被删除:

    >>> mystr = 'Arugg^]T'
    >>> myre = re.compile(ur'[^\u0041-\u005A]|[^\u0061-\u007A]', re.UNICODE)
    >>> result = myre.sub('', mystr)
    >>> result
    ''

当我在https://pythex.org/上测试正则表达式[^\u0041-\u005A]|[^\u0061-\u007A]时,它可以达到我的期望,但是当我尝试在代码中使用它时,它并没有达到我想要的目的。我想念什么?

提前谢谢!

3 个答案:

答案 0 :(得分:1)

您的正则表达式不正确,您正在使用|来检查其中一个是否正确。

您需要创建一个具有多个范围的表达式,

[^\u0041-\u005A\u0061-\u007A]将匹配范围\u0041-\u005A\u0061-\u007A以外的任何字符。

import re

regex = r"[^\u0041-\u005A\u0061-\u007A]"

test_str = "Arugg^]T"

myre = re.compile(regex, re.UNICODE)
result = myre.sub('', test_str)
print(result)

# output,
AruggT

答案 1 :(得分:0)

您要替换的所有字符

不在'[^\u0041-\u005A]'不在[^\u0061-\u007A]'中(由于^)。

如果任何一个为真,则全部替换为''-因此无论您拥有什么,它始终为真。

请改用ur'[^\u0041-\u005A\u0061-\u007A]'(两个范围都在一个[...]内。

答案 2 :(得分:0)

正则表达式正则表达式类 items 一起被 OR 组合在一起。

您的正则表达式与

相同

[\u0041-\u005a\u0061-\u007a\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u012f\u0131\u0386\u0388-\u038a]


但是对于负正则表达式类[^]被单独取反,然后 AND 在一起。

那个正则表达式就是

[^\u0041-\u005a\u0061-\u007a\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u012f\u0131\u0386\u0388-\u038a]

在逻辑上与

相同

[^\u0041-\u005A][^\u0061-\u007A][^\u00C0-\u00D6][^\u00D8-\u00F6][^\u00F8-\u012F][^\u0131][^\u0386][^\u0388-\u038A]


您尝试做的是对每个项目取反,然后对它们进行 OR
不一样。