我有一个这样的字符串:
this is "a test"
我试图在Python中写一些东西,通过空格分割它,同时忽略引号中的空格。我想要的结果是:
['this', 'is', 'a test']
PS,我知道你会问“如果引号中有引号会发生什么,在我的应用程序中,这永远不会发生。
我有一个这样的字符串:
this is "a test"
我试图在Python中写一些东西,通过空格分割它,同时忽略引号中的空格。我想要的结果是:
['this', 'is', 'a test']
PS,我知道你会问“如果引号中有引号会发生什么,在我的应用程序中,这永远不会发生。
当前回答
你需要从内置的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"']
其他回答
我看到这里的正则表达式方法看起来很复杂和/或错误。这让我很惊讶,因为正则表达式语法可以很容易地描述“空格或引号包围的东西”,而且大多数正则表达式引擎(包括Python的)都可以在正则表达式上进行拆分。所以如果你要使用正则表达式,为什么不直接说出你的意思呢?:
test = 'this is "a test"' # or "this is 'a test'"
# pieces = [p for p in re.split("( |[\\\"'].*[\\\"'])", test) if p.strip()]
# From comments, use this:
pieces = [p for p in re.split("( |\\\".*?\\\"|'.*?')", test) if p.strip()]
解释:
[\\\"'] = double-quote or single-quote
.* = anything
( |X) = space or X
.strip() = remove space and empty-string separators
不过,Shlex可能提供更多的特性。
根据你的用例,你可能还想检查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']
不同答案的速度测试:
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
由于性能原因,re似乎更快。下面是我的解决方案,使用最小贪婪操作符,保留外部引号:
re.findall("(?:\".*?\"|\S)+", s)
结果:
['this', 'is', '"a test"']
它将像aaa“bla blub”bbb这样的结构放在一起,因为这些标记没有被空格分隔。如果字符串包含转义字符,你可以这样匹配:
>>> a = "She said \"He said, \\\"My name is Mark.\\\"\""
>>> a
'She said "He said, \\"My name is Mark.\\""'
>>> for i in re.findall("(?:\".*?[^\\\\]\"|\S)+", a): print(i)
...
She
said
"He said, \"My name is Mark.\""
请注意,这也通过模式的\S部分来匹配空字符串“”。
看一下shlex模块,特别是shlex.split。
>>> import shlex
>>> shlex.split('This is "a test"')
['This', 'is', 'a test']