假设我的字符串s
包含字母和两个分隔符1
和2
。我想以下列方式拆分字符串:
t
介于1
和2
之间,请返回t
因此,如果s = 'ab1cd2efg1hij2k'
,预期输出为['a', 'b', 'cd', 'e', 'f', 'g', 'hij', 'k']
。
我尝试使用正则表达式:
import re
s = 'ab1cd2efg1hij2k'
re.findall( r'(1([a-z]+)2|[a-z])', s )
[('a', ''),
('b', ''),
('1cd2', 'cd'),
('e', ''),
('f', ''),
('g', ''),
('1hij2', 'hij'),
('k', '')]
从那里我可以[ x[x[-1]!=''] for x in re.findall( r'(1([a-z]+)2|[a-z])', s ) ]
得到答案,但我仍然不理解输出。 documentation表示如果模式包含多个组,findall
将返回元组列表。但是,我的模式只包含一个组。欢迎任何解释。
答案 0 :(得分:5)
你的模式有两组,更大的组:
(1([a-z]+)2|[a-z])
和第二个较小的组,即第一组的子集:
([a-z]+)
这是一个给你预期结果的解决方案,但是请注意,它真的很难看,而且可能有更好的方法。我无法弄清楚:
import re
s = 'ab1cd2efg1hij2k'
a = re.findall( r'((?:1)([a-z]+)(?:2)|([a-z]))', s )
a = [tuple(j for j in i if j)[-1] for i in a]
>>> print a
['a', 'b', 'cd', 'e', 'f', 'g', 'hij', 'k']
答案 1 :(得分:1)
你的正则表达式有两组,只看你正在使用的括号数:)。一组为([a-z]+)
,另一组为(1([a-z]+)2|[a-z])
。关键是你可以在其他组中包含组。因此,如果可能,您应该只使用一个组构建正则表达式,这样您就不必对结果进行后处理。
只有一个组的正则表达式示例如下:
>>> import re
>>> s = 'ab1cd2efg1hij2k'
>>> re.findall('((?<=1)[a-z]+(?=2)|[a-z])', s)
['a', 'b', 'cd', 'e', 'f', 'g', 'hij', 'k']
答案 2 :(得分:1)
如果您想在不将其分成匹配组的情况下进行“或”匹配,只需在“或”匹配的开头添加“?:”。
没有'?:'
re.findall('(test (word1|word2))', 'test word1')
Output:
[('test word1', 'word1')]
带有'?:'
re.findall('(test (?:word1|word2))', 'test word1')
Output:
['test word1']
进一步的解释:https://www.ocpsoft.org/tutorials/regular-expressions/or-in-regex/
答案 3 :(得分:0)
查看类似问题的答案:https://bugs.python.org/issue6663 如果您使用的是findall,请删除括号:
import re
s = 'ab1cd2efg1hij2k'
re.findall( r'(?<=1)[a-z]+(?=2)|[a-z]', s )
答案 4 :(得分:0)
我参加聚会已经晚了5年,但是我想我可能已经找到了一个优雅的解决方案,可以解决带有多个捕获组的re.findall()丑陋的元组输出。
通常,如果最终得到的输出看起来像这样:
[('pattern_1', '', ''), ('', 'pattern_2', ''), ('pattern_1', '', ''), ('', '', 'pattern_3')]
然后您可以通过以下小技巧将其放入平面清单:
["".join(x) for x in re.findall(all_patterns, iterable)]
预期输出如下:
['pattern_1', 'pattern_2', 'pattern_1', 'pattern_3']
它已在Python 3.7上进行了测试。希望对您有帮助!
答案 5 :(得分:0)
只需要做一个简单的更改:将组更改为非捕获组
代码:
import re
s = 'ab1cd2efg1hij2k'
re.findall( r'(1(?:[a-z]+)2|[a-z])', s )
输出:
['a', 'b', '1cd2', 'e', 'f', 'g', '1hij2', 'k']