如何用括号外的逗号分割字符串?

ken*_*der 22 python regex split

我有一串这样的格式:

"Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"
Run Code Online (Sandbox Code Playgroud)

所以基本上它是演员姓名的列表(可选地后跟他们在括号中的作用).角色本身可以包含逗号(演员姓名不能,我强烈希望如此).

我的目标是将这个字符串拆分成一对 - (actor name, actor role).

一个明显的解决方案是遍历每个角色,检查是否出现'(',')'','在外部发生逗号时将其拆分.但这看起来有点沉重......

我正在考虑使用正则表达式来拆分它:首先用括号分割字符串:

import 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', '']
Run Code Online (Sandbox Code Playgroud)

这里奇怪的元素是演员名字,甚至是角色.然后我可以用逗号分割名称,并以某种方式提取名称 - 角色对.但这似乎比我的第一种方法更糟糕.

有没有更容易/更好的方法来做到这一点,使用单个正则表达式还是一段漂亮的代码?

Lau*_*ves 19

一种方法是使用findall正则表达式,贪婪地匹配分隔符之间的事物.例如:

>>> s = "Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"
>>> r = re.compile(r'(?:[^,(]|\([^)]*\))+')
>>> r.findall(s)
['Wilbur Smith (Billy, son of John)', ' Eddie Murphy (John)', ' Elvis Presley', ' Jane Doe (Jane Doe)']
Run Code Online (Sandbox Code Playgroud)

上面的正则表达式匹配一个或多个:

  • 非逗号,非开放字符
  • 以open paren开头的字符串,包含0个或更多非close-parens,然后是close paren

关于这种方法的一个怪癖是相邻的分离器被视为单个分离器.也就是说,你不会看到一个空字符串.这可能是一个错误或功能,具体取决于您的用例.

另外请注意,正则表达式是适合在那里筑巢是一种可能性的情况下.因此,例如,这将错误地分裂:

"Wilbur Smith (son of John (Johnny, son of James), aka Billy), Eddie Murphy (John)"
Run Code Online (Sandbox Code Playgroud)

如果你需要处理嵌套,你最好的选择就是将字符串分成parens,逗号和everthing else(基本上标记它 - 这部分仍然可以用正则表达式完成),然后遍历那些重新组装字段的标记,保持跟踪嵌套级别(跟踪嵌套级别是正则表达式无法自行完成的).

  • 每当我看到有用的正则表达式时,就像这个一样,我开始怀疑 - 它们应该是人类可读的吗?或者只是我......从第一眼看不出来的人? (2认同)

Wog*_*gan 5

我认为解决这个问题的最佳方法是使用python的内置csv模块.

因为csv模块只允许一个字符quotechar,所以你需要对输入进行替换以转换()为类似|或者".然后确保你使用合适的方言然后离开.


Ala*_*ore 5

s = re.split(r',\s*(?=[^)]*(?:\(|$))', x) 
Run Code Online (Sandbox Code Playgroud)

前瞻与下一个开括号或字符串末尾的所有内容匹配,iff之间没有紧密括号.这可以确保逗号不在括号内.