【问题标题】:Python regex match string of 8 characters that contain both alphabets and numbersPython 正则表达式匹配包含字母和数字的 8 个字符的字符串
【发布时间】:2020-11-19 18:28:04
【问题描述】:

我正在尝试使用re.findall 匹配包含数字和字母(不能只有数字或字母)的长度为 8 的字符串。字符串可以以字母或字母开头,后跟任意组合。

例如-

输入字符串:The reference number is 896av6uf and not 87987647 or ahduhsjs or hn0.

输出:['896av6uf','a96bv6u0']

我想出了这个正则表达式r'([a-z]+[\d]+[\w]*|[\d]+[a-z]+[\w]*)',但是它也给了我少于 8 个字符的字符串。 需要修改正则表达式以返回恰好包含字母和字母的 8 个字符的字符串。

【问题讨论】:

  • a96bv6u0 是从哪里来的?

标签: python regex


【解决方案1】:

你可以使用

\b(?=[a-zA-Z]*[0-9])(?=[0-9]*[a-zA-Z])[a-zA-Z0-9]{8}\b
\b(?=[^\W\d_]*\d)(?=\d*[^\W\d_])[^\W_]{8}\b

第一个仅支持 ASCII 字母,而第二个支持所有 Unicode 字母和数字,因为 [^\W\d_] 匹配任何 Unicode 字母,\d 匹配任何 Unicode 数字(因为在 Python 中默认使用 re.UNICODE 选项3.x)。

详情:

  • \b - 单词边界
  • (?=[a-zA-Z]*[0-9]) - 在任何 0+ ASCII 字母之后,必须有一个数字
  • (?=[0-9]*[a-zA-Z]) - 在任何 0+ 数字之后,必须有一个 ASCII 字母
  • [a-zA-Z0-9]{8} - 八个 ASCII 字母数字字符
  • \b - 单词边界

【讨论】:

  • 你能把\w改成[a-zA-Z\d]吗,因为\w匹配896av6_u
  • @AbdessabourMtk 我添加了第二个正则表达式。
【解决方案2】:

首先,让我们查找由小写字母和数字组成的 8 个字符长的单词的语句:

\b[a-z\d]{8}\b

下一个条件是单词必须同时包含字母和数字:

[a-d]\d

现在是具有挑战性的部分,将这些组合成一个陈述。最简单的方法可能是把它们吐出来,但我们可以使用一些前瞻来让它发挥作用:

\b(?=.*[a-z]\d)[a-z\d]{8}\b

我确信有一种更整洁的方法可以做到这一点,但这会奏效。

【讨论】:

    【解决方案3】:

    你可以使用\b\w{8}\b

    它不保证您将同时拥有数字和字母,但保证您将拥有恰好八个字符,并被单词边界(例如空格、行首/行尾)包围。

    您可以在以下在线游乐场中尝试一下:https://regex101.com/

    匹配的内容是用\w{8} 完成的,这意味着8 个字母/单词(包括大写和下划线)。 \b 表示“单词边界”

    如果您只需要数字和小写字母,请将其替换为 \b[a-z0-9]{8}\b

    然后您可以进一步检查是否存在两个数字和字母,例如通过使用filter:

    list(filter(lambda s: re.search(r'[0-9]', s) and re.search(r'[a-z]', s), result))

    result 是你从re.findall() 得到的。

    所以底线,我会使用:

    list(filter(lambda s: re.search(r'[0-9]', s) and re.search(r'[a-z]', s), re.findall(r'\b[a-z0-9]{8}\b', str)))

    【讨论】:

    • 我第二个正则表达式 101。很棒的工具。
    • @benji 但是,它不符合 .NET 正则表达式风格。您不能在模式中使用平衡构造,也不能使用字符类减法。
    【解决方案4】:

    比其他人建议的更紧凑的解决方案是:

    ((?![A-Za-z]{8}|[0-9]{8})[0-9A-Za-z]{8})
    

    这保证找到的匹配项长度为 8 个字符,并且它们不能只是数字或字母。

    细分:

    • (?![A-Za-z]{8}|[0-9]{8}) = 这是一个否定的前瞻,这意味着匹配不能是 8 个数字或 8 个字母的字符串。
    • [0-9A-Za-z]{8} = 简单的正则表达式,表示输入必须是长度为 8 个字符的字母数字。

    测试用例:

    输入:12345678 abcdefgh i8D0jT5Yu6Ms1GNmrmaUjicc1s9D93aQBj3WWWjww54gkiKqOd7Ytkl0MliJy9xadAgcev8b2UKdfGRDOpxRPm30dw9GeEz3WPRO 1234567890987654321 qwertyuiopasdfghjklzxcvbnm

    import re
    
    pattern = re.compile(r'((?![A-Za-z]{8}|\d{8})[A-Za-z\d]{8})')
    
    test = input()
    match = pattern.findall(test)
    print(match)
    

    输出:['i8D0jT5Y', 'u6Ms1GNm', 'maUjicc1', 's9D93aQB', 'j3WWWjww', '54gkiKqO', 'd7Ytkl0M', 'liJy9xad', 'Agcev8b2', 'DOpxRPm3', '0dw9GeEz']

    【讨论】:

    • (?:\b|\B) 对匹配没有影响,可以删除。此外,(?![A-Za-z]{8}|[0-9]{8})[0-9A-Za-z]{8} 是错误的模式,因为它可以匹配超过 8 个字符的部分单词。
    • @WiktorStribiżew 感谢您的建议,我现在删除了多余的(?:\b|\B)。但是,我想指出,我打算让匹配在部分单词上起作用,因为从未指定匹配由空格分隔。如果需要,这种模式可以更灵活地进行微调。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 2016-01-16
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多