python输⼊逗号分隔_关于python:如何⽤括号外的逗号分割
字符串?
我得到了这样的格式的字符串:
1"Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"
因此从根本上讲,它是演员姓名的列表(可选地,其后是括号中的⾓⾊)。 ⾓⾊本⾝可以包含逗号(演员的名字不能,我强烈希望如此)。
我的⽬标是将此字符串拆分为成对的列表-(actor name, actor role)。
⼀个显⽽易见的解决⽅案是遍历每个字符,检查'(',')'和','的出现情况,并在出现逗号时将其拆分。 但这似乎有点沉重...
我正在考虑使⽤正则表达式拆分它:⾸先⽤括号将字符串拆分:
1
2
3
4import re
x ="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"
s = re.split(r'[()]', x)
# ['Wilbur Smith ', 'Billy, son of John', ', Eddie Murphy ', 'John', ', Elvis Presley, Jane Doe ', 'Jane Doe', '']
这⾥的奇数元素是演员名称,甚⾄是⾓⾊。 然后我可以⽤逗号分隔名称,并以某种⽅式提取名称⾓⾊对。 但是,这似乎⽐我的第⼀种⽅法还要糟糕。
是否有任何更简单/更好的⽅法来执⾏此操作,⽽只需⼀个正则表达式或⼀段不错的代码?
⼀种⽅法是将findall与正则表达式⼀起使⽤,该正则表达式贪婪地匹配分隔符之间可能会发⽣的事情。例如:
1
2
3
4>>> s ="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"
>>> r = repile(r'(?:[^,(]|\([^)]*\))+')
>>> r.findall(s)
['Wilbur Smith (Billy, son of John)', ' Eddie Murphy (John)', ' Elvis Presley', ' Jane Doe (Jane Doe)']
上⾯的正则表达式匹配⼀个或多个:
⾮逗号,⾮开放字符
以开放括号开头的字符串,包含0个或多个⾮封闭括号,然后是封闭括号
关于此⽅法的⼀个怪癖是将相邻的分隔符视为单个分隔符。也就是说,您不会看到⼀个空字符串。根据您的⽤例,这可能是错误或功能。
还要注意,正则表达式不适⽤于可能嵌套的情况。因此,例如,这将错误地拆分:
1"Wilbur Smith (son of John (Johnny, son of James), aka Billy), Eddie Murphy (John)"
如果您需要处理嵌套,则最好的选择是将字符串分成括号,逗号和其他所有内容(本质上是对其进⾏标记化-这部分仍可以使⽤正则表达式来完成),然后遍历这些标记重新组合字段,并保持跟踪嵌套级别(正则表达式⽆法⾃⾏执⾏的嵌套级别跟踪)。
您可以通过匹配记录⽽不是分隔符⽴即将其分为⼏个字段:[(m.group(" name"),m.group(" role")))for re.findall("(?P 。+ ?)(?(?P [^] +)(, s * | $))",x)]
如果需要,可以为令牌解决⽅案+1。上下⾏⾛时弹出堆栈,这是⼀种经典的⽅法。
每当我看到正则表达式有⽤时,就像我这样,我就开始怀疑-它们是否是⼈类可读的?还是它只是我...乍看之下谁看不见?
好答案。谢谢劳伦斯!如果我想这样做但不在输出中括号内包含内容,该如何解决这个问题?
@ user815423426在这种情况下,Id可能使⽤的⽅法是对结果列表进⾏第⼆次传递并删除括号。例如:r = [re.sub(r\([^)]*\), , s) for s in r]之类的东西。如果您需要更详细的答案,则可能应该发布⼀个单独的问题。
1s = re.split(r',\s*(?=[^)]*(?:\(|$))', x)
先⾏匹配下⼀个开括号或字符串末尾的所有内容,前提是两者之间没有闭括号。这样可以确保逗号不在括号内。
我认为解决此问题的最佳⽅法是使⽤python内置的csv模块。
由于csv模块仅允许⼀个字符quotechar,因此您需要对输⼊进⾏替换以将()转换为类似|或"的字符。然后确保您使⽤的是适当的⽅⾔,然后离开。
尝试⼈类可读的正则表达式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import re
regex = repile(r"""
# name starts and ends on word boundary
# no '(' or commas in the name
(?P\b[^(,]+\b)
\s*
# everything inside parentheses is a role
(?P[^)]+)
\))? # role is optional
""", re.VERBOSE)
s = ("Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley,"
"Jane Doe (Jane Doe)")
print re.findall(regex, s)
输出:
1
2[('Wilbur Smith', 'Billy, son of John'), ('Eddie Murphy', 'John'),
('Elvis Presley', ''), ('Jane Doe', 'Jane Doe')]
可读的正则表达式-是不是⽭盾词?
这篇⽂章对我有很⼤帮助。 我想⽤引号外的逗号分隔字符串。 我⽤它作为⼊门。 我的最后⼀⾏代码是regEx = repile(r'(?:[^,"]|" [^"]*")+')。 万分感谢。
这是我过去⽤于此类情况的通⽤技术:
将re模块的sub函数与函数作为替换参数⼀起使⽤。该函数跟踪打开和关闭括号,⽅括号和花括号以及单引号和双引号,并且仅在此类带括号和引号的⼦字符串之外执⾏替换。然后,您可以⽤您确定不会出现在字符串中的另⼀个字符替换⽆括号/带引号的逗号(我使⽤ASCII / Unicode组分隔符:chr(29)代码),然后执⾏⼀个简单的字符串。在那个⾓⾊上分裂。这是代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import re
def srchrepl(srch, repl, string):
"""Replace non-bracketed/quoted occurrences of srch with repl in string""" resrchrepl = repile(r"""(?P[([{])|(?P['"])|(?P["""
+ srch +"""])|(?P[)\]}])""")
return resrchrepl.sub(_subfact(repl), string)
def _subfact(repl):
"""Replacement function factory for regex sub method in srchrepl."""
level = 0
qtflags = 0
def subf(mo):
nonlocal level, qtflags
sepfound = mo.group('sep')
if sepfound:
if level == 0 and qtflags == 0:
return repl
else:
up(0)
up('lbrkt'):
level += 1
up(0)
up('quote') =="'":
qtflags ^= 1 # toggle bit 1
return"'"
up('quote') == '"':
qtflags ^= 2 # toggle bit 2
return '"'
up('rbrkt'):
level -= 1
up(0)
return subf
如果您的Python版本中没有nonlocal,只需将其更改为global并在模块级别定义level和qtflags。
使⽤⽅法如下:
1
2
3
4
5>>> GRPSEP = chr(29)
>>> string ="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"
正则表达式获取括号内容>>> lst = srchrepl(',', GRPSEP, string).split(GRPSEP)
>>> lst
['Wilbur Smith (Billy, son of John)', ' Eddie Murphy (John)', ' Elvis Presley', ' Jane Doe (Jane Doe)']
我的答案将不使⽤正则表达式。
我认为状态为in_actor_name的简单字符扫描程序应该可以⼯作。请记住,状态" in_actor_name"在此状态下以')'或逗号终⽌。我的尝试:
1
2
3
4
5
6
7
8