如何使用正则表达式在Python中匹配所有Unicode小写字符?

3
我正在尝试编写一个正则表达式,以匹配Python 3中的Unicode小写字符。我正在使用re库。例如,re.findall(some_pattern, 'u∏ñKθ')应该返回['u', 'ñ', 'θ']
在Sublime Text中,我可以简单地键入[[:lower:]]来查找这些字符。
我知道Python可以使用re.compile('[^\W\d_]')匹配任何Unicode字符,但我需要明确区分大小写。我也知道re.compile('[a-z]')将匹配任何ASCII小写字符,但我的数据是UTF-8,并且包括许多非ASCII字符——我已经检查过了。
在Python 3中,正则表达式是否能够实现这个功能,还是我需要采用其他方法?我知道其他的方式来完成,只是希望能使用正则表达式。

您可以在某些Python逻辑的基础上使用正则表达式。 - PCM
1
这个回答解决了你的问题吗?使用正则表达式如何查找仅包含大写或小写字母的字符串 - fsimonjetz
@fsimonjetz 不,它不能处理所有非ASCII字符。 - PCM
5个回答

5
你可以使用支持POSIX字符类的正则表达式模块
import regex 

>>> regex.findall('[[:lower:]]', 'u∏ñKθ')
['u', 'ñ', 'θ']

或者,使用\p{Ll}\p{Lowercase_Letter}Unicode类别类
>>> regex.findall(r'\p{Ll}', 'u∏ñKθ')
['u', 'ñ', 'θ']

或者只需使用Python的字符串逻辑:

>>> [c for c in 'u∏ñKθ' if c.islower()]
['u', 'ñ', 'θ']

在任何情况下,都要注意像这样的字符串:

>>> s2='\u0061\u0300\u00E0'
>>> s2
'àà'

第一个 音素 'à' 是由带有组合字符 '̀''a' 组成的,而第二个 'à' 是由该特定代码点生成的。如果在此处使用字符类,则会匹配 'a' 而不是组合重音符号:
>>> regex.findall('[[:lower:]]', s2)
['a', 'à']
>>> [c for c in s2 if c.islower()]
['a', 'à']

为了解决这个问题,您需要在更复杂的正则表达式模式中考虑到这一点,或者规范化字符串
>>> regex.findall('[[:lower:]]', unicodedata.normalize('NFC',s2))
['à', 'à']

或者逐个字符遍历:

>>> [c for c in regex.findall(r'\X', s2) if c.islower()]
['à', 'à']

我很感激这个提示。我一直试图避免使用.islower(),因为我没有透露问题的部分是我正在寻找几个特定的字符类型组合,例如一个大写字母后跟至少一个小写字母,同时还允许一些特殊字符。这就是为什么我特别想要一个正则表达式。我会安装并使用regex模块。谢谢! - Nik

3
你可以使用 regex 包,如果使用第三方包是可以接受的。
>>> import regex
>>> s = 'ABCabcÆæ'
>>> m = regex.findall(r'[[:lower:]]', s)
>>> m
['a', 'b', 'c', 'æ']

我通常对第三方软件包持谨慎态度,但如果我可以通过conda访问它,而这个特定的软件包可以,那么冒险一试也是值得的。看起来这将是我最好的选择。谢谢! - Nik

1

您不需要使用PyPi regex库(尽管我建议在这里使用它,因为它支持POSIX字符类(如[:lower:])和Unicode属性类,例如\p{Ll}):

import re, sys
lower = '[{}]'.format("".join([chr(i) for i in range(sys.maxunicode) if chr(i).islower()]))
print(re.findall(lower, 'ABCabcÆæóżźę'))
# => ['a', 'b', 'c', 'æ', 'ó', 'ż', 'ź', 'ę']

查看 Python证明

结果:

['a', 'b', 'c', 'æ', 'ó', 'ż', 'ź', 'ę']

0
我创建了以下Python脚本来获取所有小写字母,根据islower()字符串方法,并 找到连续的范围 来创建一个大字符类正则表达式,用于识别所有小写字母。
import itertools, re, sys

lowercaseOrdinals = [i for i in range(sys.maxunicode) if chr(i).islower()]

def ranges(i):
    for a, b in itertools.groupby(enumerate(i), lambda pair: pair[1] - pair[0]):
        b = list(b)
        yield b[0][1], b[-1][1]

lowercaseRegex = '['
for startRangeOrdinal, endRangeOrdinal in ranges(lowercaseOrdinals):
    if startRangeOrdinal == endRangeOrdinal:
        lowercaseRegex += chr(startRangeOrdinal)
    else:
        lowercaseRegex += chr(startRangeOrdinal) + '-' + chr(endRangeOrdinal)    lowercaseRegex += ']'

with open('lower.txt', 'w', encoding='utf-8') as fileObj:
    fileObj.write(lowercaseRegex)

它生成的872个字符长的字符类正则表达式匹配任何小写Unicode字符,这里:

[a-zªµºß-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıijĵķ-ĸĺļľŀłńņň-ʼnŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźżž-ƀƃƅƈƌ-ƍƒƕƙ-ƛƞơƣƥƨƪ-ƫƭưƴƶƹ-ƺƽ-ƿdžljnjǎǐǒǔǖǘǚǜ-ǝǟǡǣǥǧǩǫǭǯ-ǰdzǵǹǻǽǿȁȃȅȇȉȋȍȏȑȓȕȗșțȝȟȡȣȥȧȩȫȭȯȱȳ-ȹȼȿ-ɀɂɇɉɋɍɏ-ʓʕ-ʸˀ-ˁˠ-ˤͅͱͳͷͺ-ͽΐά-ώϐ-ϑϕ-ϗϙϛϝϟϡϣϥϧϩϫϭϯ-ϳϵϸϻ-ϼа-џѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿҁҋҍҏґғҕҗҙқҝҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӂӄӆӈӊӌӎ-ӏӑӓӕӗәӛӝӟӡӣӥӧөӫӭӯӱӳӵӷӹӻӽӿԁԃԅԇԉԋԍԏԑԓԕԗԙԛԝԟԡԣԥԧԩԫԭԯՠ-ֈა-ჺჽ-ჿᏸ-ᏽᲀ-ᲈᴀ-ᶿḁḃḅḇḉḋḍḏḑḓḕḗḙḛḝḟḡḣḥḧḩḫḭḯḱḳḵḷḹḻḽḿṁṃṅṇṉṋṍṏṑṓṕṗṙṛṝṟṡṣṥṧṩṫṭṯṱṳṵṷṹṻṽṿẁẃẅẇẉẋẍẏẑẓẕ-ẝẟạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹỻỽỿ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶ-ᾷιῂ-ῄῆ-ῇῐ-ΐῖ-ῗῠ-ῧῲ-ῴῶ-ῷⁱⁿₐ-ₜℊℎ-ℏℓℯℴℹℼ-ℽⅆ-ⅉⅎⅰ-ⅿↄⓐ-ⓩⰰ-ⱞⱡⱥ-ⱦⱨⱪⱬⱱⱳ-ⱴⱶ-ⱽⲁⲃⲅⲇⲉⲋⲍⲏⲑⲓⲕⲗⲙⲛⲝⲟⲡⲣⲥⲧⲩⲫⲭⲯⲱⲳⲵⲷⲹⲻⲽⲿⳁⳃⳅⳇⳉⳋⳍⳏⳑⳓⳕⳗⳙⳛⳝⳟⳡⳣ-ⳤⳬⳮⳳⴀ-ⴥⴧⴭꙁꙃꙅꙇꙉꙋꙍꙏꙑꙓꙕꙗꙙꙛꙝꙟꙡꙣꙥꙧꙩꙫꙭꚁꚃꚅꚇꚉꚋꚍꚏꚑꚓꚕꚗꚙꚛ-ꚝꜣꜥꜧꜩꜫꜭꜯ-ꜱꜳꜵꜷꜹꜻꜽꜿꝁꝃꝅꝇꝉꝋꝍꝏꝑꝓꝕꝗꝙꝛꝝꝟꝡꝣꝥꝧꝩꝫꝭꝯ-ꝸꝺꝼꝿꞁꞃꞅꞇꞌꞎꞑꞓ-ꞕꞗꞙꞛꞝꞟꞡꞣꞥꞧꞩꞯꞵꞷꞹꞻꞽꞿꟃꟈꟊꟶꟸ-ꟺꬰ-ꭚꭜ-ꭨꭰ-ꮿff-stﬓ-ﬗa-z--------------------------------]

此外,这个正则表达式的大写版本共有839个字符,可以在这里找到:

[A-ZÀ-ÖØ-ÞĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸ-ŹŻŽƁ-ƂƄƆ-ƇƉ-ƋƎ-ƑƓ-ƔƖ-ƘƜ-ƝƟ-ƠƢƤƦ-ƧƩƬƮ-ƯƱ-ƳƵƷ-ƸƼDŽLJNJǍǏǑǓǕǗǙǛǞǠǢǤǦǨǪǬǮDZǴǶ-ǸǺǼǾȀȂȄȆȈȊȌȎȐȒȔȖȘȚȜȞȠȢȤȦȨȪȬȮȰȲȺ-ȻȽ-ȾɁɃ-ɆɈɊɌɎͰͲͶͿΆΈ-ΊΌΎ-ΏΑ-ΡΣ-ΫϏϒ-ϔϘϚϜϞϠϢϤϦϨϪϬϮϴϷϹ-ϺϽ-ЯѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎҐҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾӀ-ӁӃӅӇӉӋӍӐӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӶӸӺӼӾԀԂԄԆԈԊԌԎԐԒԔԖԘԚԜԞԠԢԤԦԨԪԬԮԱ-ՖႠ-ჅჇჍᎠ-ᏵᲐ-ᲺᲽ-ᲿḀḂḄḆḈḊḌḎḐḒḔḖḘḚḜḞḠḢḤḦḨḪḬḮḰḲḴḶḸḺḼḾṀṂṄṆṈṊṌṎṐṒṔṖṘṚṜṞṠṢṤṦṨṪṬṮṰṲṴṶṸṺṼṾẀẂẄẆẈẊẌẎẐẒẔẞẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼẾỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỬỮỰỲỴỶỸỺỼỾἈ-ἏἘ-ἝἨ-ἯἸ-ἿὈ-ὍὙὛὝὟὨ-ὯᾸ-ΆῈ-ΉῘ-ΊῨ-ῬῸ-Ώℂℇℋ-ℍℐ-ℒℕℙ-ℝℤΩℨK-ℭℰ-ℳℾ-ℿⅅⅠ-ⅯↃⒶ-ⓏⰀ-ⰮⱠⱢ-ⱤⱧⱩⱫⱭ-ⱰⱲⱵⱾ-ⲀⲂⲄⲆⲈⲊⲌⲎⲐⲒⲔⲖⲘⲚⲜⲞⲠⲢⲤⲦⲨⲪⲬⲮⲰⲲⲴⲶⲸⲺⲼⲾⳀⳂⳄⳆⳈⳊⳌⳎⳐⳒⳔⳖⳘⳚⳜⳞⳠⳢⳫⳭⳲꙀꙂꙄꙆꙈꙊꙌꙎꙐꙒꙔꙖꙘꙚꙜꙞꙠꙢꙤꙦꙨꙪꙬꚀꚂꚄꚆꚈꚊꚌꚎꚐꚒꚔꚖꚘꚚꜢꜤꜦꜨꜪꜬꜮꜲꜴꜶꜸꜺꜼꜾꝀꝂꝄꝆꝈꝊꝌꝎꝐꝒꝔꝖꝘꝚꝜꝞꝠꝢꝤꝦꝨꝪꝬꝮꝹꝻꝽ-ꝾꞀꞂꞄꞆꞋꞍꞐꞒꞖꞘꞚꞜꞞꞠꞢꞤꞦꞨꞪ-ꞮꞰ-ꞴꞶꞸꞺꞼꞾꟂꟄ-ꟇꟉꟵA-Z------------------------------------]

-1
尝试一下这个 -
import re

a = re.findall('[^\W\d_]', 'u∏ñKθ')

for i in a:
    if i.islower():
        print(i)

re.findall 找到所有的 UTF-8 字符,然后用 .islower() 过滤它们,以检查它们是否是小写字符,然后打印出来


不必使用for循环,简单的列表推导式就足够了。我会给你的回答点个踩,因为你也给我的回答点了踩。 - user9321739
列表推导式用于构建列表。在这里,我正在打印值而不是列表。 - PCM
谢谢!我简化了我的问题以使它更清晰。完整的问题和我想要使用正则表达式的原因是,我正在寻找特定字符类型的组合。例如,一个大写字母后跟1个或多个小写字母或特定特殊字符。当我对Python的re库感到沮丧时,最初我用lambda函数写出所有这些规则,但它们很丑,所以我进行了第二次尝试。不过还是谢谢你的建议! - Nik

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