2013-11-24 15 views
1

我試圖分割字符串,如下面的標題,並匹配名稱,然後任何其他信息,無論是括號/大括號或破折號後,m/n破折號,單槓)。使用Python的re模塊匹配正則表達式組(帶或者)和特殊字符

正則表達式對我來說看起來很好,我可以在其他正則表達式測試器上測試它,但在使用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

哎呦,發現我離開了'IndexError'從我被一個數字索引訪問組時趕上!衛生署。 –

回答

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] 
– 
+0

啊,這是總的感覺,我沒有意識到你可以指定一個字符串文字是一個unicode原始字符串!當我通過索引訪問組而不是按名稱訪問組時,我也意外地離開了這些try/catch塊。使用'或'作爲添加組更清潔;-)感謝您的幫助! –

+1

@MichaelWaterfall,我忘記提及'match.group('addition_a')'總是返回一些東西(str/None),即使沒有'addition_a'組匹配。 'addition_b'一樣。 – falsetru

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>.+)[\)\]]))$' 

否則,或者如果你不控制,就可以使一個小的修改哪一個 - 雖然不是完全正確的 - 將會RK。這種變化是從集[-–—―]接受多個字符,而不是一個單一的一個做[-–—―]+

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'} 
+0

感謝您的解釋,使總體感覺!我不知道你可以有一個unicode原始字符串。你每天都會學到新的東西;-) –

2

與稍微更「爬犁hammery」的辦法是改變整個再是「一些詞和空格,直到它不是,然後是其餘的「。這也避免了可選的additional_aadditional_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'} 
+0

這真的很有趣。雖然它不太適合我的目的,但它並沒有一半表明Python有多驚人!謝謝你。 –

相關問題