使用交替运算符匹配多个正则表达式模式



我在使用Python-Regex时遇到了一个小问题。

假设这是输入:

(zyx)bc

我试图实现的是获得括号之间的任何字符作为单个匹配,以及外部的任何字符为单个匹配。预期的结果将是:

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

比赛的顺序应该保持。

我已经尝试过用Python3.3获得这个,但似乎无法找到正确的Regex。到目前为止,我有:

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

print(matches)产生以下结果:

['zyx','','']

你知道我做错了什么吗?

来自re.findall:的文档

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

当regexp与字符串匹配三次时,(.*?)组在后两次匹配中为空。如果您想要regexp的另一半的输出,您可以添加第二组:

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

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

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

不过,您需要手动删除括号。

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

>>> 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

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

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

哎哟,里面只有一个subpattern,但re.findall只有在subpattern存在的情况下才能拉出!

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']

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

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

或者使用更多的组,然后处理生成的元组以获得您要查找的字符串:

>>> [''.join(t) for t in re.findall(r'((.+?))|(w)', '(zyx)bc')]
>>> ['zyx', 'b', 'c']
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']

最新更新