我有一个这样的字符串:

this is "a test"

我试图在Python中写一些东西,通过空格分割它,同时忽略引号中的空格。我想要的结果是:

['this', 'is', 'a test']

PS,我知道你会问“如果引号中有引号会发生什么,在我的应用程序中,这永远不会发生。


当前回答

嗯,好像找不到“回复”按钮了…不管怎样,这个答案是基于Kate的方法,但正确地分割了包含转义引号的子字符串,并删除了子字符串的开始和结束引号:

  [i.strip('"').strip("'") for i in re.split(r'(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')', string) if i.strip()]

这适用于'这是' a \\\"test\\\"\\\'s子字符串' '这样的字符串(不幸的是,为了防止Python删除转义,这个疯狂的标记是必要的)。

如果返回列表中的字符串不需要转义,您可以使用稍微修改过的函数版本:

[i.strip('"').strip("'").decode('string_escape') for i in re.split(r'(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')', string) if i.strip()]

其他回答

我用shlex。拆分来处理七千万行鱿鱼日志,太慢了。所以我换成了re。

请尝试这个,如果你有性能问题与shlex。

import re

def line_split(line):
    return re.findall(r'[^"\s]\S*|".+?"', line)

嗯,好像找不到“回复”按钮了…不管怎样,这个答案是基于Kate的方法,但正确地分割了包含转义引号的子字符串,并删除了子字符串的开始和结束引号:

  [i.strip('"').strip("'") for i in re.split(r'(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')', string) if i.strip()]

这适用于'这是' a \\\"test\\\"\\\'s子字符串' '这样的字符串(不幸的是,为了防止Python删除转义,这个疯狂的标记是必要的)。

如果返回列表中的字符串不需要转义,您可以使用稍微修改过的函数版本:

[i.strip('"').strip("'").decode('string_escape') for i in re.split(r'(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')', string) if i.strip()]

作为一个选项,尝试tssplit:

In [1]: from tssplit import tssplit
In [2]: tssplit('this is "a test"', quote='"', delimiter='')
Out[2]: ['this', 'is', 'a test']

你需要从内置的shlex模块中分离。

>>> import shlex
>>> shlex.split('this is "a test"')
['this', 'is', 'a test']

这应该是你想要的效果。

如果你想保留引号,那么你可以传递posix=False kwarg。

>>> shlex.split('this is "a test"', posix=False)
['this', 'is', '"a test"']

不同答案的速度测试:

import re
import shlex
import csv

line = 'this is "a test"'

%timeit [p for p in re.split("( |\\\".*?\\\"|'.*?')", line) if p.strip()]
100000 loops, best of 3: 5.17 µs per loop

%timeit re.findall(r'[^"\s]\S*|".+?"', line)
100000 loops, best of 3: 2.88 µs per loop

%timeit list(csv.reader([line], delimiter=" "))
The slowest run took 9.62 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 2.4 µs per loop

%timeit shlex.split(line)
10000 loops, best of 3: 50.2 µs per loop