我想在Python的逗号处拆分一个Python多行字符串,除非逗号位于括号内的表达式中。例如,绳子
{J. Doe, R. Starr}, {Lorem
{i}psum dolor }, Dol. sit., am. et.分拆成
['{J. Doe, R. Starr}', '{Lorem\n{i}psum dolor }', 'Dol. sit.', 'am. et.']这涉及到括号匹配,因此可能regexes在这里没有帮助。PyParsing有commaSeparatedList,除了引用的(")环境是受保护的,而不是{}-delimited环境,它几乎可以满足我的需要。
有什么暗示吗?
发布于 2014-11-07 19:52:08
编写您自己的自定义拆分函数:
input_string = """{J. Doe, R. Starr}, {Lorem
{i}psum dolor }, Dol. sit., am. et."""
expected = ['{J. Doe, R. Starr}', '{Lorem\n{i}psum dolor }', 'Dol. sit.', 'am. et.']
def split(s):
parts = []
bracket_level = 0
current = []
# trick to remove special-case of trailing chars
for c in (s + ","):
if c == "," and bracket_level == 0:
parts.append("".join(current))
current = []
else:
if c == "{":
bracket_level += 1
elif c == "}":
bracket_level -= 1
current.append(c)
return parts
assert split(input_string), expected发布于 2014-11-07 20:00:12
在这种情况下,您可以使用re.split:
>>> from re import split
>>> data = '''\
... {J. Doe, R. Starr}, {Lorem
... {i}psum dolor }, Dol. sit., am. et.'''
>>> split(',\s*(?![^{}]*\})', data)
['{J. Doe, R. Starr}', '{Lorem\n{i}psum dolor }', 'Dol. sit.', 'am. et.']
>>>下面是Regex模式匹配的说明:
, # Matches ,
\s* # Matches zero or more whitespace characters
(?! # Starts a negative look-ahead assertion
[^{}]* # Matches zero or more characters that are not { or }
\} # Matches }
) # Closes the look-ahead assertion发布于 2016-03-31 08:00:58
卢卡斯·特兹涅夫斯基的评论实际上可以在PyPi正则模中使用(我刚刚用一个编号的组替换了命名组,以使它更短):
>>> import regex
>>> r = regex.compile(r'({(?:[^{}]++|\g<1>)*})(*SKIP)(*FAIL)|\s*,\s*')
>>> s = """{J. Doe, R. Starr}, {Lorem
{i}psum dolor }, Dol. sit., am. et."""
>>> print(r.split(s))
['{J. Doe, R. Starr}', None, '{Lorem\n{i}psum dolor }', None, 'Dol. sit.', None, 'am. et.']模式- ({(?:[^{}]++|\g<1>)*})(*SKIP)(*FAIL) -匹配{...{...{}...}...}类结构(因为{匹配{,(?:[^{}]++|\g<1>)*匹配0+出现的2种替代: 1)除{和} ( [^{}]++)以外的任何1+字符,2)匹配整个({(?:[^{}]++|\g<1>)*})子模式的文本)。(*SKIP)(*FAIL)谓词使引擎忽略匹配缓冲区中的整个匹配值,因此,将索引移到匹配的末尾,不保存返回的任何内容(我们“跳过”了匹配的内容)。
\s*,\s*匹配一个用0+空格括起来的逗号。
出现None值是因为第一个分支中有一个捕获组,在第二个分支匹配时为空。我们需要在第一个可供选择的分支中使用一个捕获组进行递归。若要删除空元素,请使用“理解”:
>>> print([x for x in r.split(s) if x])
['{J. Doe, R. Starr}', '{Lorem\n{i}psum dolor }', 'Dol. sit.', 'am. et.']https://stackoverflow.com/questions/26808913
复制相似问题