2013-02-28 80 views
3

首先,我是新來的正則表達式。但到目前爲止,我愛上了他們。我正在使用正則表達式從我從渲染引擎獲取的圖像文件名稱中提取信息。到目前爲止,這正則表達式是工作體面......蟒蛇正則表達式給出空字符串

_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$ 

如果我使用split()方法上的一個文件名,如...

image_file_name_ao.0001.exr

我回來我可以使用的漂亮的小列表...

['image_file_name', 'gi', None, '.', '0001', 'exr', ''] 

我唯一擔心的是它總是最後返回一個空字符串。無論我如何更改或操縱正則表達式,它總是在列表的末尾給我一個空字符串。我完全理解忽略它並繼續前進,但我的問題是我是否正在使用我的正則表達式做錯了什麼,或者我能做些什麼來使它不傳遞最終的空字符串?感謝您的時間。

+0

見我的答案 請問你的問題。但是爲什麼你想使用''re.split''而不是捕獲組,就像在Katzwinkel的回答中那樣? - 順便說一下,爲什麼不在「(\ d {1,2})?」和最後一個點之前分組捕獲潛在的不良內容? – eyquem 2013-02-28 22:08:50

回答

3

難怪。 split方法在正則表達式出現時分割你的字符串(加上返回組範圍)。而且,由於你的正則表達式僅到達直至線(在其端部由$表示)的結束串匹配,有沒有在文件名的結束分裂,但空的後綴('')。

鑑於您已在表達式中使用組「(...)」,因此您最好使用re.match(regex, string)。這會給你一個MatchObject實例,從中你可以檢索通過groups()包含一個元組的組:

# additional group up front 
reg='(\S*)_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$' 
print re.match(reg, filename).groups() # request tuple of group matches 

編輯:我真的很抱歉,但我沒有意識到您的模式不匹配文件名字符串從它的第一個字符開始。我在回答中擴展了它。如果你想堅持使用你的方法,使用split(),你也可以改變你的原始模式,使文件名的最後一部分不匹配,因此分裂。

+0

感謝您的快速回答。我已經嘗試了match()方法,但是我只收到一個NoneType。我已經通過編譯正則表達式以及上面解釋的方式來嘗試它,但沒有影響。我上面使用的測試字符串與split()方法一起工作良好,但從未使用match()方法工作。 – 2013-02-28 21:15:16

+0

您可能沒有注意到我對答案所做的修訂。它的工作原理就像現在所顯示的那樣。嘗試're.match('(\ S *)_([az] {2,8})_?(\ d {1,2})?(\。| _)(\ d {3,10}) \。([a-z] {2,6})$','image_file_name_ao.0001.exr')。groups()',我向你保證它會做到這一點。我很抱歉的混淆! – 2013-02-28 21:19:31

+0

我完全錯過了那個補充,我的錯。現在它工作得很好,非常感謝你的幫助。 – 2013-02-28 21:32:17

1

有趣的問題。

我改變一點點正則表達式的模式:

import re 

reg = re.compile('_([a-z]{2,8})' 

       '_?(\d\d?)?' 

       '([._])' 
       '(\d{3,10})' 
       '\.' 
       '(?=[a-z]{2,6}$)') 

for ss in ('image_file_name_ao.0001.exr', 
      'image_file_name_45_ao.0001.exr', 
      'image_file_name_ao_78.0001.exr', 
      'image_file_name_ao78.0001.exr'): 
    print '%s\n%r\n' % (ss, reg.split(ss)) 

結果

image_file_name_ao.0001.exr 
['image_file_name', 'ao', None, '.', '0001', 'exr'] 

image_file_name_45_ao.0001.exr 
['image_file_name_45', 'ao', None, '.', '0001', 'exr'] 

image_file_name_ao_78.0001.exr 
['image_file_name', 'ao', '78', '.', '0001', 'exr'] 

image_file_name_ao78.0001.exr 
['image_file_name', 'ao', '78', '.', '0001', 'exr'] 
+0

我已經花了大部分時間去了解re.split()在與我所做的一切都更加絕望。現在你出現了,突然間我明白了!感謝您以強調個人模式的方式重新排列表達方式。並提醒組內特殊字符。 – 2013-02-28 22:11:44

+0

@Katzwinkel事實上,乍一看,我不清楚OP的代碼是如何給出結果的。所以我和你一樣,在模式中定義了幾個組時,我研究了''re.split''的函數。然後,我回答了這個問題,這是一個XY問題的Y問題。 (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)您回答了X問題。所以我提出了你值得接受的答案。 – eyquem 2013-02-28 22:39:05

+0

謝謝您再次啓發我,@eyquem。我從來不知道有這樣一個專門的術語,但它對我來說很有意義。很多時候,我覺得難以確定OP中的實際問題。另一方面,新用戶起初可能會感受到壓力,因爲沒有顯示出足夠的個人努力證據而貶低其他人的問題。許多人可能覺得他們應該提出至少一些東西,不久之後,十個人再次處理'Y'。在這個項目上工作很有趣,我很高興能夠學到這麼多東西。乾杯! – 2013-02-28 23:20:37

1

您可以使用filter()

鑑於您的例子,這會工作像,

def f(x): 
    return x != '' 

filter 
(
    f, 
    re.split('_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$', 
    'image_file_name_ao.0001.exr') 
)