我正在尝试拆分字符串,如下面的标题,并匹配名称,然后匹配任何其他信息,在括号/大括号中或破折号后(常规,m / n破折号,水平条)。
正则表达式对我来说似乎很好,我可以在其他正则表达式测试器上测试它,但是在使用Python运行时它不起作用。
有几件奇怪的事情正在发生。第一个虚线标题似乎已匹配,但addition_a
组不包含正确的字符串。此外,由于某种原因,任何特殊字符(如各种破折号)根本不匹配。脚本的编码是utf-8所以我假设原始正则表达式字符串中的破折号应该可以正常工作,但它们不是。
# -*- coding: utf-8 -*-
import re
titles = [
'Spaced (News)',
'Angry Birds [Game]',
'Cheats - for all games', # dash
'Cheats – for all games', # ndash
'Cheats — for all games', # mdash
'Cheats ― for all games' # horizontal bar
]
regex = re.compile(r'^(?P<name>.+)\s+(([-–—―]\s+(?P<addition_a>.+))|([\(\[](?P<addition_b>.+)[\)\]]))$')
for title in titles:
data = {}
match = regex.match(title.strip())
if match:
data['name'] = match.group('name')
try:
data['addition'] = match.group('addition_a')
except IndexError:
pass
try:
data['addition'] = match.group('addition_b')
except IndexError:
pass
print data
输出:
{'addition': 'News', 'name': 'Spaces'}
{'addition': 'Game', 'name': 'Angry Birds'}
{'addition': None, 'name': 'Cheats'}
{}
{}
{}
答案 0 :(得分:2)
使用unicode文字。否则,[-–—―]
匹配-
,\xe2
,\x80
,\x93
,\xe2
,\x80
,\x94
, \xe2
,\x80
,\x95
代替-
,–
,—
,―
# -*- coding: utf-8 -*-
import re
titles = [
u'Spaced (News)',
u'Angry Birds [Game]',
u'Cheats - for all games', # dash
u'Cheats – for all games', # ndash
u'Cheats — for all games', # mdash
u'Cheats ― for all games' # horizontal bar
]
regex = re.compile(ur'^(?P<name>.+)\s+(([-–—―]\s+(?P<addition_a>.+))|([\(\[](?P<addition_b>.+)[\)\]]))$')
for title in titles:
match = regex.match(title.strip())
if match:
data = {}
data['name'] = match.group('name')
data['addition'] = match.group('addition_a') or match.group('addition_b')
print data
输出:
{'addition': u'News', 'name': u'Spaced'}
{'addition': u'Game', 'name': u'Angry Birds'}
{'addition': u'for all games', 'name': u'Cheats'}
{'addition': u'for all games', 'name': u'Cheats'}
{'addition': u'for all games', 'name': u'Cheats'}
{'addition': u'for all games', 'name': u'Cheats'}
>>> r'[–]'
'[\xe2\x80\x93]'
>>> re.findall(r'[–]', '–')
['\xe2', '\x80', '\x93']
>>> re.findall(ur'[–]', u'–')
[u'\u2013']
>>> print re.findall(ur'[–]', u'–')[0]
–
答案 1 :(得分:2)
Unicode有“字符”或“符号”占用多个字节,Python不太擅长理解这个概念,因此有时会有一些小问题。您可以执行以下操作之一:
您可以尝试确保您要解析的所有字符串都是unicode,如果您控制这些字符串应该很简单 - 例如,只需将u
指示符添加到字符串的开头即可像这样:
u'Spaced (News)',
u'Angry Birds [Game]',
u'Cheats - for all games', # dash
u'Cheats – for all games', # ndash
u'Cheats — for all games', # mdash
u'Cheats ― for all games' # horizontal bar
并将其添加到正则表达式中,如下所示:
ur'^(?P<name>.+)\s+(([-–—―]\s+(?P<addition_a>.+))|([\(\[](?P<addition_b>.+)[\)\]]))$'
否则,或者如果你无法控制,你可以做一个小的修改 - 虽然不完全正确 - 会起作用。该更改是接受来自[-–—―]
集的多个字符,而不只是通过[-–—―]+
接受单个字符:
r'^(?P<name>.+)\s+(([-–—―]+\s+(?P<addition_a>.+))|([\(\[](?P<addition_b>.+)[\)\]]))$'
这些选项中的任何一个都会产生你想要的东西。
第一个将导致unicode结果:
>>>
{'addition': u'News', 'name': u'Spaced'}
{'addition': u'Game', 'name': u'Angry Birds'}
{'addition': None, 'name': u'Cheats'}
{'addition': None, 'name': u'Cheats'}
{'addition': None, 'name': u'Cheats'}
{'addition': None, 'name': u'Cheats'}
常规字符串中的第二个:
>>>
{'addition': 'News', 'name': 'Spaced'}
{'addition': 'Game', 'name': 'Angry Birds'}
{'addition': None, 'name': 'Cheats'}
{'addition': None, 'name': 'Cheats'}
{'addition': None, 'name': 'Cheats'}
{'addition': None, 'name': 'Cheats'}
答案 2 :(得分:2)
稍微多一点“雪橇”的方式是将整个重新改为“一些词语和空格,直到它不是,然后是其余的”。这也避免了可选的additional_a
和additional_b
命名组以及try / except逻辑。
示例:
for title in titles:
data = dict(zip(['name', 'addition'], (m.strip() for m in re.findall('([\w\s]+)', title))))
print data
输出:
{'addition': 'News', 'name': 'Spaced'}
{'addition': 'Game', 'name': 'Angry Birds'}
{'addition': 'for all games', 'name': 'Cheats'}
{'addition': 'for all games', 'name': 'Cheats'}
{'addition': 'for all games', 'name': 'Cheats'}
{'addition': 'for all games', 'name': 'Cheats'}