在python中提取嵌套正则表达式的所有匹配项

时间:2009-10-27 22:16:53

标签: python regex parsing

我正在尝试解析满足python正则表达式的项目列表

r'\A(("[\w\s]+"|\w+)\s+)*\Z'

也就是说,它是一个以空格分隔的列表,除了在引用的字符串中允许使用空格。我想获得列表中的项目列表(与

匹配的项目
r'("[\w\s]+"|\w+)'

一部分。所以,例如

>>> parse('foo "bar baz" "bob" ')
['foo', '"bar baz"', '"bob"']

使用python re有什么好办法吗?

很多事情都不太奏效。例如

>>> re.match(r'\A(("[\w\s]+"|\w+)\s+)*\Z', 'foo "bar baz" "bob" ').group(2)
'"bob"'

仅返回匹配的最后一个。另一方面

>>> re.findall(r'("[\w\s]+"|\w+)', 'foo "bar baz" "bob" ')
['foo', '"bar baz"', '"bob"']

但它也接受格式错误的表达式,如

>>> re.findall(r'("[\w\s]+"|\w+)', 'foo "bar b-&&az" "bob" ')
['foo', 'bar', 'b', 'az', '" "', 'bob']

那么有没有办法使用原始正则表达式并获得与第2组匹配的所有项目?像

这样的东西
>>> re.match_multigroup(r'\A(("[\w\s]+"|\w+)\s+)*\Z', 'foo "bar baz" "bob" ').group(2)
['foo', '"bar baz"', '"bob"']
>>> re.match_multigroup(r'("[\w\s]+"|\w+)', 'foo "bar b-&&az" "bob" ')
None

编辑: 非常重要,我保留输出中的引号,因此我不想

>>> re.match_multigroup(r'\A(("[\w\s]+"|\w+)\s+)*\Z', 'foo "bar baz" "bob" ').group(2)
['foo', 'bar baz', 'bob']

因为那时我不知道bob是否被引用。

3 个答案:

答案 0 :(得分:2)

我不认为正则表达式是正确的工具。试试csv模块:

>>> s = 'foo "bar baz" "bob" '
>>> for i in csv.reader([s], delimiter=' '):
    print(i)


['foo', 'bar baz', 'bob', '']

答案 1 :(得分:1)

这是一个解决方案,可以拆分任何不在一对引号内的空格:

re.split('\s+(?=[^"]*(?:"[^"]*"[^"]*)*$)', target)

只有在刚好匹配的空格之前有偶数个引号时,前瞻才会成功。如果文本中的引用部分可以包含转义引号,则可能需要更复杂的正则表达式,具体取决于转义的执行方式。

答案 2 :(得分:1)

好吧,我最终分两步决定这样做。

首先,我检查表达式在语法上是否有效,然后我将其分解为单个部分:

def parse(expr):
    if re.match(r'\A(("[\w\s]+"|\w+)\s+)*\Z', expr):
        return re.findall(r'("[\w\s]+"|\w+)', expr)

所以:

>>> parse('foo "bar baz" "bob" ')
['foo', '"bar baz"', '"bob"']
>>> parse('foo "bar b-&&az" "bob" ')
>>> parse('foo "bar" ')
['foo', '"bar"']
>>> parse('"foo" bar ')
['"foo"', 'bar']
>>> parse('foo"bar baz" "bob" ')
>>> parse('&&')

我大约90%确定这种方法对所有字符串都适用,但如果有人有更通用的解决方案,我仍然会感兴趣,这对我来说似乎有点麻烦。

感谢SilentGhost和Alan Moore的帮助。我以前不了解python csv或regex lookaheads,对我来说,了解它们可能会有所帮助。