2016-09-20 353 views
4

我需要找到匹配模式的所有字符串,但两个给定字符串除外。正则表达式匹配除字符串外的所有字符

例如,找到除aabb之外的所有字母组。从这个字符串开始:

-a-bc-aa-def-bb-ghij- 

应返回:

('a', 'bc', 'def', 'ghij') 

我试着用this regular表达,抓住4串。我认为我正在接近,但(1)它在Python中不起作用,(2)我无法弄清楚如何从搜索中排除几个字符串。 (是的,我可以稍后删除它们,但是我真正的正则表达式只能一次完成所有操作,我希望在其中包含最后一步。)

我说它在Python中不起作用,因为我试过这个,期待完全相同的结果,而是我得到的只有第一组:

>>> import re 
>>> re.search('-(\w.*?)(?=-)', '-a-bc-def-ghij-').groups() 
('a',) 

我负尝试一下未来,但我无法找到这种情况下,一个可行的解决方案。

+0

你想['findall'](https://docs.python.org/2/library/re.html#re.findall) - 'search'只能返回第一个匹配:) – cxw

回答

6

您可以使用负的样子aheads的。

例如,

>>> re.findall(r'-(?!aa|bb)([^-]+)', string) 
['a', 'bc', 'def', 'ghij'] 

  • -相配-

  • (?!aa|bb)负先行,检查是否-后面没有aabb

  • ([^-]+)相配ONY或比其它多个字符-


编辑

上述正则表达式不匹配的那些,其与aabb启动,例如像-aabc-。要照顾,我们可以添加-到喜欢向前看符号,

>>> re.findall(r'-(?!aa-|bb-)([^-]+)', string) 
+0

仅供参考:'(?!aa | bb)'lookahead不允许那些* aa或bb开头的匹配项。所以说,'aacn' [不会匹配](https://regex101.com/r/jR5sH1/1)。 –

+0

@WiktorStribiżew有效点。我为答案添加了一个编辑。感谢您指出:) – nu11p01n73R

+0

是的,我只是认为最后的'-'实际上是必需的 - 只是由OP输入字符串来判断。如果最后没有'-',你的正则表达式会返回一个匹配,我的不会。这一点尚不清楚,但我猜得到了一个倒退。 –

2

您需要使用负向前视来限制更一般的模式,并且需要使用re.findall来查找所有匹配项。

使用

res = re.findall(r'-(?!(?:aa|bb)-)(\w+)(?=-)', s) 

或 - 如果您在连字符之间的值可以是任何而是一个连字符,请使用否定的字符类[^-]

res = re.findall(r'-(?!(?:aa|bb)-)([^-]+)(?=-)', s) 

这里是regex demo

详细

  • - - 一个连字符
  • (?!(?:aa|bb)-) - 如果第一个连字符后aa-bb-,不匹配应退还
  • (\w+) - 第1组(该值将由re.findall呼叫返回)捕获1个或更多字词[^-]+ - 1个或更多字符除了-
  • (?=-) - 字符后面必须有一个-。在这里需要预先保证重叠匹配(因为这个连字符将成为下一场比赛的起点)。

Python demo

import re 
p = re.compile(r'-(?!(?:aa|bb)-)([^-]+)(?=-)') 
s = "-a-bc-aa-def-bb-ghij-" 
print(p.findall(s)) # => ['a', 'bc', 'def', 'ghij'] 
+0

我会在这里也加上这句话:我认为最后一次比赛是必须的,因为最后一场比赛只有跟着'-'才有效。这是从OP字符串中推导出来的,所以不太确定。 –

0

虽然正则表达式溶液要求,我认为这个问题可以用更简单的Python函数,即字符串分割和过滤来解决简单:

input_list = "-a-bc-aa-def-bb-ghij-" 
exclude = set(["aa", "bb"]) 
result = [s for s in input_list.split('-')[1:-1] if s not in exclude] 

此解决方案有额外的优点result也可以变成一台发电机和结果列表并不需要显式地构建。

相关问题