我正在尝试解析满足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是否被引用。
答案 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,对我来说,了解它们可能会有所帮助。