【问题标题】:Regex | Empty String match | Python 3.4.0正则表达式 |空字符串匹配 | Python 3.4.0
【发布时间】:2021-02-24 07:29:36
【问题描述】:

我的代码:

import re

#Phone Number regex
phoneRegex = re.compile(r'''(
(\d{3}|\(\d{3}\))?
(\s|-|\.)?                       # separator
(\d{3})                          # first 3 digits
(\s|-|\.)                        # separator
(\d{4})                          # last 4 digits
(\s*(ext|x|ext.)\s*(\d{2,5}))?   # extension
)''', re.VERBOSE)

phoneRegex.findall('Phone: 800.420.7240 or +1 415.863.9900 (9 a.m. to 5 p.m., M-F, PST)')

输出:

[('800.420.7240', '800', '.', '420', '.', '7240', '', '', ''), ('415.863.9900', '415', '.', '863', '.', '9900', '', '', '')]

问题:

  1. 为什么匹配中包含空字符串?
  2. 从字符串的哪些位置匹配空字符串?
  3. 空字符串匹配的条件是什么?

附言 当我在 https://regex101.com/ 上使用相同的正则表达式时,匹配中不包含空字符串 另外,我几天前才开始学习正则表达式,如果我的问题不够好,我很抱歉。

【问题讨论】:

    标签: python python-3.x regex


    【解决方案1】:

    ? 运算符意味着它将返回零或一个匹配。在这种情况下,您使用? 将一些捕获组设为可选,python 将为您创建的三个可选捕获组中的每一个返回一个长度为零的匹配项。

    如果您删除前两个?,您将消除一些零长度匹配。要处理最后一个,您需要更改扩展模式。它占了两个,同样因为您使用 零或一个 运算符 (*)。

    如果您不关心内部捕获组并且只想要完整匹配,则可以使用类似的东西过滤掉零长度匹配

    >>> [match.group(0) for match in phoneRegex.finditer('Phone: 800.420.7240 or +1 415.863.9900 (9 a.m. to 5 p.m., M-F, PST)')]
    ['800.420.7240', '415.863.9900']
    

    您可以使扩展捕获组匹配条件为前面的电话号码匹配。另外,我认为您可能需要在第三种选择ext. 中转义.。如所写,它匹配 任何 字符,但我认为您的意思是 ext\.

    供参考:

    【讨论】:

    • 感谢您的回答!即使删除了前两个 (?) 运算符,我仍然得到 3 个空字符串匹配项。我在删除 (*) 运算符后尝试运行代码,但我仍然不断得到 3 个空字符串匹配项。但是,当我删除最后一个 (?) 运算符(与 'extension' 一起使用)时,我没有得到任何匹配。
    【解决方案2】:

    为什么匹配中包含空字符串? 因为您在正则表达式中使用了各种组。引擎会捕获您放入组中的匹配部分。

    从字符串的哪些位置匹配空字符串? 从这个正则表达式:(\s*(ext|x|ext.)\s*(\d{2,5}))? 它有三组(你可以数左括号)。引擎找不到与扩展名匹配的内容,并且尝试捕获信息的 3 个组返回空字符串。

    空字符串匹配的条件是什么? 如果您以引擎在匹配的字符串中捕获空子字符串的方式对正则表达式进行分组,它将返回空字符串:-)

    我认为您正在遵循“使用 python 自动化无聊的东西”的练习。在第 178 页的 VERBOSE 模式下的正则表达式中,尝试查找左括号。右括号在哪里?组的数量与左括号的数量相等。整个正则表达式的组号为零。

    如果您想提取匹配字符串的某些部分,组很有用。如果您只想提取完整的电话号码,请远离群组。

    你可以试试这个:

    phoneRegex = re.compile(r'\d{3}[\.|-|\/]\d{3}[\.|-|\/]\d{4}')
    

    这是你想要达到的目标吗?

    如果您想在 VERBOSE 模式下坚持使用您的正则表达式,您也可以使用非捕获组。这仅捕获完整匹配:

    phoneRegex = re.compile(r'''(
    (?:\d{3}|\(?:\d{3}\))?
    (?:\s|-|\.)?                       # separator
    (?:\d{3})                          # first 3 digits
    (?:\s|-|\.)                        # separator
    (?:\d{4})                          # last 4 digits
    (?:\s*(?:ext|x|ext.)\s*(?:\d{2,5}))?   # extension
    )''', re.VERBOSE)
    

    【讨论】:

      猜你喜欢
      • 2023-03-13
      • 2020-11-29
      • 2011-11-28
      • 1970-01-01
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      相关资源
      最近更新 更多