【问题标题】:Strange regex issue using findall() and search() [duplicate]使用 findall() 和 search() 的奇怪正则表达式问题 [重复]
【发布时间】:2018-12-03 02:27:40
【问题描述】:

我正在尝试使用 \w{2}\d/\d{1,2}(/\d{1,2})? 来匹配以下两个接口在 Cisco 交换机上:

Gi1/0/1

Fa0/1

  1. 当我使用 re.search() 时,它会返回所需的输出。

    import re
    port = "Gi1/0/1 Fa0/1"
    search = re.search(r'\w{2}\d/\d{1,2}(/\d{1,2})?', port)
    print search.group()
    

我得到 "Gi1/0/1" 作为输出。

  1. 当我使用 re.findall()

    import re
    port = "Gi1/0/1 Fa0/1"
    search = re.findall(r'\w{2}\d/\d{1,2}(/\d{1,2})?', port)
    print search
    

我得到了不想要的 "['/1', '']"

为什么 findall() 不返回 ['Gi1/0/1','Fa0/1']

是不是因为我使用了 (/\d{1,2})?,而 findall() 应该返回这部分?这是为什么?

我们如何使用 findall() 获得 ['Gi1/0/1','Fa0/1']

【问题讨论】:

    标签: python regex python-2.7 search findall


    【解决方案1】:

    来自findall 文档

    如果模式中存在一个或多个组,则返回一个列表 团体;如果模式有多个,这将是一个元组列表 组。

    在你的正则表达式中你有一个捕获组(/\d{1,2})?

    您可以将其设为非捕获组 (?:/\d{1,2})?

    你的正则表达式看起来像:

    \w{2}\d/\d{1,2}(?:/\d{1,2})?

    import re
    port = "Gi1/0/1 Fa0/1"
    search = re.findall(r'\w{2}\d/\d{1,2}(?:/\d{1,2})?', port)
    print search
    

    Demo

    【讨论】:

    • 非常感谢,我会尝试这个技巧使其成为非捕获组。
    【解决方案2】:

    search.group() 返回由正则表达式 \w{2}\d/\d{1,2}(/\d{1,2})? 找到的整个匹配项。它考虑捕获组。它相当于search.group(0)。使用search.group(1)时,会返回/1:第一个捕获组的结果。

    另一方面,re.findall 返回匹配组的所有结果。为了得到预期的结果,你的正则表达式应该是

    (\w{2}\d/(?:\d{1,2}/)?\d{1,2})
    

    Python 代码

    >>> re.findall(r'(\w{2}\d/(?:\d{1,2}/)?\d{1,2})', port)
    ['Gi1/0/1', 'Fa0/1']
    

    正则表达式分解

    ( #Start Capturing group
      \w{2}\d/  #Match two characters in [A-Za-z0-9_] followed by a digit and slash
      (?:\d{1,2}/)? #Followed by two digits which are optional
      \d{1,2} #Followed by two digits
    ) #End capturing group
    

    P.S. 从您的问题来看,我认为您只匹配字母。在这种情况下,使用[A-Za-z] 而不是\w

    【讨论】:

    • 非常感谢您的详细回复,我学到了一些新东西,非常感谢!
    【解决方案3】:

    如果你想要正则表达式;这将起作用:

    search = re.findall(r'\w{2}\d/\d{1}(?:/\d{1})?', port)
    

    你也可以这样做:

    >>> "Gi1/0/1 Fa0/1".split(' ')
    ['Gi1/0/1', 'Fa0/1']
    

    【讨论】:

    • 感谢您的回答。接口名称会因 Cisco 交换机的型号而异,有些型号是 Gigabitethernet,有些是 FastEthernet。我有另一个更大的脚本来捕获不同交换机上的这些接口。这里我只是提供了一个示例代码来理解 search() 和 findall() 之间的区别。
    • 哦,好吧。我明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 2017-03-01
    • 2023-03-31
    相关资源
    最近更新 更多