2013-10-21 68 views
2

我有一個模板字符串,像這樣封閉所有的模板表達式:檢測不被大括號

'%album_artist%/%album%{ (%year%)}/{%track_number%. }%track_artist% - %title%'

我想找到的所有變量,這是不可選的,因此不被大括號括:, title,album_artistalbum但不是track_numberyear

目前,我的表情是'(?<![{])%([A-Za-z_]+)%(?![}])',但它也匹配year

爲了讓正則表達式不會被大括號內的變量名或多個變量附加字符混淆,我需要改變什麼?我使用Python的re

相關問題:

+1

你使用什麼風味/語言? – HamZa

+0

我使用Python的re – moi

回答

2

如果你使用PHP,您可以使用此模式:

~{[^}]*+}(*SKIP)(*FAIL)|%\w++%~i 

舉例:

preg_match_all('~{[^}]*+}(*SKIP)(*FAIL)|%\w++%~i', $string, $matches); 
print_r($matches); 

如果您使用Python,你可以做同樣的伎倆(即:以前匹配的大括號的內容,然後搜索你在找什麼)與捕獲組:

import re 

mystr = r'%album_artist%/%album%{ (%year%)}/{%track_number%. }%track_artist% - %title%'; 
print filter(bool, re.findall(r'{[^}]*|(?i)%(\w+)%', mystr)) 

注意:

你可以試試這個其他模式左大括號(不肯定它比第一速度更快),之後將停止比賽在最後%

print filter(bool, re.findall(r'{(?:[^}%]*%)*|(?i)%(\w+)%', mystr)) 
+1

這是什麼'(* SKIP)(* FAIL)'構造?我從來沒有見過它,而RegexBuddy 4不知道它。 –

+2

@TimPietzcker:啊哈!這是一個PCRE功能。這些動詞是爲回溯控制而設計的。 SKIP表示前一個子模式不能成功,FAIL強制子模式失敗(如'(?!)')。目標是避免空結果不像'\ K' –

+0

令人遺憾的是,Python're'不能很好地支持PCRE。 – moi

0

您可以嘗試使用替代方法,只對與花括號不匹配的分支進行分組。它會返回空白字符串的結果,你可以過濾掉,如:

>>> import re 
>>> s = r'''%album_artist%/%album%{ (%year%)}/{%track_number%. }%track_artist% - %title%''' 
>>> list(filter(lambda e: e.strip(), re.findall(r'\{[^}]*\}|%([^%]*)%', s))) 
['album_artist', 'album', 'track_artist', 'title'] 
+0

它的工作原理,謝謝!但是,像Casimirs的回答那樣,使用'filter(bool,...)'會更短。 – moi