我有一个字符串,如下所示:
this is "a test"
我正在尝试用Python编写一些东西,用空格分割,同时忽略引号内的空格.我正在寻找的结果是:
['this','is','a test']
PS.我知道你会问"如果报价中有引号会发生什么,那么,在我的申请中,这将永远不会发生.
您希望从shlex模块拆分.
>>> import shlex >>> shlex.split('this is "a test"') ['this', 'is', 'a test']
这应该完全符合你的要求.
shlex
特别是看看模块shlex.split
.
>>> import shlex >>> shlex.split('This is "a test"') ['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']
我使用shlex.split处理70,000,000行鱿鱼日志,它太慢了.所以我改用了.
如果你有shlex的性能问题,请试试这个.
import re def line_split(line): return re.findall(r'[^"\s]\S*|".+?"', line)
由于此问题标有正则表达式,我决定尝试使用正则表达式方法.我首先用\ x00替换引号部分中的所有空格,然后用空格分割,然后将\ x00替换回每个部分中的空格.
两个版本都做同样的事情,但拆分器比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)
似乎出于性能原因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
模式的一部分匹配空字符串。