下面是我要用逗号分割的字符串。
如果()或{}中包含逗号,则不应拆分该字符串。
我正在使用以下代码进行拆分:
目前仅处理(),我如何也包含{}?
import re
s = "Water,^.*f04.*&~(.*z.,*)$,Iron Oxides (CI 77491, 77492),a{3,4}"
print re.split(r',\s*(?![^()]*\))', s)
输出应为:
[Water,^.*f04.*&~(.*z.,*)$,Iron Oxides (CI 77491, 77492),a{3,4}]
答案 0 :(得分:1)
假设方括号可以嵌套,那么您所用的不是普通语言。尽管re
确实有很多扩展名可以处理实际的正则表达式以外的内容,但最好还是用一个简单的方括号计数解析器来解决这个问题。
类似这样的东西(未经测试,但应该足够简单以了解和调试):
bracketmap = {'(': ')', '[': ']', '{': '}'}
def splitify(s):
stack = []
lastcomma = 0
for i, c in enumerate(s):
if not stack and c == ',':
yield s[lastcomma:i]
lastcomma = i+1
elif c in bracketmap:
stack.append(bracketmap[c])
elif c in ')]}':
if stack.pop() != c:
raise ValueError('unbalanced brackets')
if stack:
raise ValueError('unbalanced brackets')
if lastcomma <= len(s):
yield s[lastcomma:]
在评论中,当被问到方括号是否可以嵌套时,您说:
如果它似乎是有效的正则表达式就可以。
因此,如果该字符串实际上是要作为正则表达式模式的,则您需要做的不只是排除括号内的逗号。例如,\{,\}
不是大括号内的逗号,而是完全正常的文字逗号。
编写一个完整的regex解析器显然比仅计算括号对要复杂一些(尽管如果您确实需要Python re
语法,则可以使用该库进行编译,然后使用该库的调试工具扫描文字原边,而不是自己编写……),但是也许您可以只计算未转义的括号对就可以逃脱?
esc = False
for i, c in enumerate(s):
if esc:
esc = False
elif c = '\\':
esc = True
elif not stack and c == ',':
# same as before
(我在这里假设您不想将\,
当作字面逗号。如果您这样做,那是微不足道的更改。)
答案 1 :(得分:1)
借助regex
模块,该模块允许在后面进行变长查找:
regex.split(r'(?<![({][^,]*),(?![^,]*[})])', str_)
(?<![({][^,]*)
是一个零宽度的负向后方,确保,
之前没有(
或{
并且没有,
在两者之间
,
匹配文字,
(?![^,]*[})])
是零宽度的负向超前行,可确保,
后没有任何中间,
后跟)
或{{1} }
示例:
}
限制:
In [1287]: str_ = "Water,^.*f04.*&~(.*z.,*)$,Iron Oxides (CI 77491, 77492),a{3,4}"
In [1288]: regex.split(r'(?<![({][^,]*),(?![^,]*[})])', str_)
Out[1288]: ['Water', '^.*f04.*&~(.*z.,*)$', 'Iron Oxides (CI 77491, 77492)', 'a{3,4}']
匹配[({]
/ (
中的任何一个,而{
匹配[})]
/ )
中的任何一个,因此可以导致错误,例如子字符串以}
开头,以(
结束,或者以其他方式结束
不适用于嵌套的括号/括号