我有一个这样的字符串:

this is "a test"

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

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

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


当前回答

由于这个问题带有正则表达式,我决定尝试正则表达式方法。我首先将引号部分中的所有空格替换为\x00,然后按空格分割,然后将\x00替换回每个部分中的空格。

这两个版本都做同样的事情,但是splitter比splitter2更具可读性。

import re

s = 'this is "a test" some text "another test"'

def splitter(s):
    def replacer(m):
        return m.group(0).replace(" ", "\x00")
    parts = re.sub('".+?"', replacer, s).split()
    parts = [p.replace("\x00", " ") for p in parts]
    return parts

def splitter2(s):
    return [p.replace("\x00", " ") for p in re.sub('".+?"', lambda m: m.group(0).replace(" ", "\x00"), s).split()]

print splitter2(s)

其他回答

试试这个:

  def adamsplit(s):
    result = []
    inquotes = False
    for substring in s.split('"'):
      if not inquotes:
        result.extend(substring.split())
      else:
        result.append(substring)
      inquotes = not inquotes
    return result

一些测试字符串:

'This is "a test"' -> ['This', 'is', 'a test']
'"This is \'a test\'"' -> ["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

根据你的用例,你可能还想检查csv模块:

import csv
lines = ['this is "a string"', 'and more "stuff"']
for row in csv.reader(lines, delimiter=" "):
    print(row)

输出:

['this', 'is', 'a string']
['and', 'more', 'stuff']

你需要从内置的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"']

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

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

import re

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