Python正则表达式 - 无关的匹配

时间:2013-05-10 18:44:08

标签: python regex

我想使用-+====+和空格作为分隔符来拆分字符串。我想保留分隔符,除非它是空格。

我尝试使用以下代码实现此目的:

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  return pattern.split(s)

print(tokenize("hello-+==== =+  there"))

我预计输出为

['hello', '-', '+=', '==', '=', '=', '+', 'there']

但是我得到了

['hello', '-', '', '+=', '', '==', '', '=', '', None, '', '=', '', '+', '', None, 'there']

这几乎是我想要的,除了有很多无关的None和空字符串。

为什么它会以这种方式运行,我怎样才能改变它以获得我想要的东西?

5 个答案:

答案 0 :(得分:3)

re.split默认返回匹配之间的字符串位数组:(如@Laurence Gonsalves所说,这是它的主要用途。)

['hello', '', '', '', '', '', '', '', 'there']

请注意-+=+===之间的空字符串等。

正如文档所解释的那样,因为您正在使用捕获组(即,因为您使用的是(\-|\+\=|\=\=|\=|\+)而不是(?:\-|\+\=|\=\=|\=|\+),所以捕获组匹配的位是散布的:

['hello', '-', '', '+=', '', '==', '', '=', '', None, '', '=', '', '+', '', None, 'there']

None对应于您的模式的\s+一半匹配的位置;在那些情况下,捕获组没有捕获任何东西。

从查看re.split的文档,我看不到一种简单的方法让它在匹配之间丢弃空字符串,尽管简单的列表理解(或filter,如果你愿意)可以很容易丢弃None和空字符串:

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  return [ x for x in pattern.split(s) if x ]

最后一个注释:对于您到目前为止所描述的内容,这样可以正常工作,但根据项目的方向,您可能需要切换到正确的解析库。 The Python wiki对这里的一些选项有很好的概述。

答案 1 :(得分:2)

为什么会这样?

根据re.split的文档:

  

如果在模式中使用捕获括号,则模式中所有组的文本也将作为结果列表的一部分返回。

这是完全正确的:如果使用捕获括号,则返回所有组的文本,无论它们是否匹配任何内容;那些不匹配的东西会返回None

split一样,两个连续的分隔符被认为是分隔空字符串,因此你会散布空字符串。

如何更改它以获得我想要的内容?

最简单的解决方案是过滤输出:

filter(None, pattern.split(s))

答案 2 :(得分:2)

或许re.findall更适合你?

>>> re.findall(r'-|\+=|==|=|\+|[^-+=\s]+', "hello-+==== =+  there")
['hello', '-', '+=', '==', '=', '=', '+', 'there']

答案 3 :(得分:1)

此模式更符合您的要求:

\s*(\-|\+\=|\=\=|\=|\+)\s*

但是,您仍然会在每次拆分之间获得一个空字符串,正如您所期望的那样。

答案 4 :(得分:0)

试试这个:

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  x = pattern.split(s)
  result = []
  for item in x:
    if item != '' and item != None:
      result.append(item)
  return result

print(tokenize("hello-+==== =+  there"))