【问题标题】:Matching multiple regex patterns with the alternation operator?使用交替运算符匹配多个正则表达式模式?
【发布时间】:2013-01-06 12:55:00
【问题描述】:

我在使用 Python 正则表达式时遇到了一个小问题。

假设这是输入:

(zyx)bc

我想要实现的是获得括号之间的任何内容作为单个匹配项,并将任何外部字符作为单个匹配项。期望的结果将是:

['zyx','b','c']

应保持匹配顺序。

我已尝试使用 Python 3.3 获取此信息,但似乎无法找出正确的正则表达式。到目前为止,我有:

matches = findall(r'\((.*?)\)|\w', '(zyx)bc')

print(matches) 产生以下结果:

['zyx','','']

任何想法我做错了什么?

【问题讨论】:

  • 这只是一个示例输入。正则表达式应该能够区分不同的情况,例如 (ab)(bc)(ca)、abc、(abc)(abc)(abc) 或 (zyx)bc 等,同时识别哪些字符在其中括号,哪些不是。

标签: python regex regex-alternation


【解决方案1】:

来自re.findall的文档:

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

虽然您的正则表达式匹配字符串三次,但后两次匹配的 (.*?) 组为空。如果你想要正则表达式的另一半的输出,你可以添加第二组:

>>> re.findall(r'\((.*?)\)|(\w)', '(zyx)bc')
[('zyx', ''), ('', 'b'), ('', 'c')]

或者,您可以删除所有组以再次获得简单的字符串列表:

>>> re.findall(r'\(.*?\)|\w', '(zyx)bc')
['(zyx)', 'b', 'c']

您需要手动删除括号。

【讨论】:

  • 仅供参考:感谢您的回答。删除括号:'matches = [match.strip('()') for match in findall(r'(.*?)|\w', case)]'
【解决方案2】:

其他答案已向您展示了如何获得所需的结果,但需要手动删除括号的额外步骤。如果您在正则表达式中使用环视,则无需手动去除括号:

>>> import re
>>> s = '(zyx)bc'
>>> print (re.findall(r'(?<=\()\w+(?=\))|\w', s))
['zyx', 'b', 'c']

解释:

(?<=\() // lookbehind for left parenthesis
\w+     // all characters until:
(?=\))  // lookahead for right parenthesis
|       // OR
\w      // any character

【讨论】:

  • 好主意。但是,如果我想在一些 .txt 文件中按我想要的顺序一一替换 3 个正则表达式,我该怎么做?
【解决方案3】:

让我们看看使用re.DEBUG 的输出。

branch 
  literal 40 
  subpattern 1 
    min_repeat 0 65535 
      any None 
  literal 41 
or
  in 
    category category_word

哎呀,里面只有一个subpattern,但re.findall 只会在存在subpatterns 的情况下取出!

a = re.findall(r'\((.*?)\)|(.)', '(zyx)bc',re.DEBUG); a
[('zyx', ''), ('', 'b'), ('', 'c')]
branch 
  literal 40 
  subpattern 1 
    min_repeat 0 65535 
      any None 
  literal 41 
or
  subpattern 2 
    any None

更好。 :)

现在我们只需要把它变成你想要的格式。

[i[0] if i[0] != '' else i[1] for i in a]
['zyx', 'b', 'c']

【讨论】:

    【解决方案4】:

    文档提到特别对待组,所以不要在括号中的模式周围放置组,你会得到一切,但你需要自己从匹配的数据中删除括号:

    >>> re.findall(r'\(.+?\)|\w', '(zyx)bc')
    ['(zyx)', 'b', 'c']
    

    或使用更多组,然后处理生成的元组以获取您寻找的字符串:

    >>> [''.join(t) for t in re.findall(r'\((.+?)\)|(\w)', '(zyx)bc')]
    >>> ['zyx', 'b', 'c']
    

    【讨论】:

      【解决方案5】:
      In [108]: strs="(zyx)bc"
      
      In [109]: re.findall(r"\(\w+\)|\w",strs)
      Out[109]: ['(zyx)', 'b', 'c']
      
      In [110]: [x.strip("()") for x in re.findall(r"\(\w+\)|\w",strs)]
      Out[110]: ['zyx', 'b', 'c']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-01
        • 2014-05-06
        • 1970-01-01
        • 2017-10-08
        • 1970-01-01
        • 2013-11-18
        • 2017-09-26
        相关资源
        最近更新 更多