7

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

我尝试使用以下代码来实现这一点:

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

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

我希望输出是

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

然而我得到了

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

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

为什么它会这样,我该如何改变它以获得我想要的?

4

5 回答 5

3

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

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

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

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

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

None对应\s+于匹配模式的一半的位置;在这些情况下,捕获组什么也没捕获。

通过查看 re.split 的文档,我没有看到一种简单的方法让它在匹配之间丢弃空字符串,尽管简单的列表理解(或filter,如果您愿意)可以轻松丢弃Nones 和空字符串:

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

最后一点:对于您到目前为止所描述的内容,这将正常工作,但根据您的项目的发展方向,您可能需要切换到适当的解析库。 Python wiki很好地概述了这里的一些选项。

于 2013-05-10T18:54:39.407 回答
2

也许re.findall会更适合你?

>>> re.findall(r'-|\+=|==|=|\+|[^-+=\s]+', "hello-+==== =+  there")
['hello', '-', '+=', '==', '=', '=', '+', 'there']
于 2013-05-10T19:08:01.213 回答
2

为什么会这样?

根据 re.split 的文档:

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

这在字面上是正确的:如果使用捕获括号,则返回所有组的文本,无论它们是否匹配;那些不匹配的返回None

与往常一样split,两个连续的定界符被视为分隔空字符串,因此您会得到散布的空字符串。

我该如何改变它以获得我想要的东西?

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

filter(None, pattern.split(s))
于 2013-05-10T19:01:23.643 回答
1

这种模式更符合你想要的:

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

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

于 2013-05-10T18:52:40.727 回答
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"))
于 2013-05-10T19:04:59.200 回答