2016-02-25 64 views
0

我有這個字符串:Python的正則表達式,排除引號比賽

s = MY_FUNC(AVG, WFC US EQUITY, WFC US EQUITY, ">+3%", 1,1,7) 

而這正則表達式,搜索括號,逗號和簡單的操作符。我需要排除雙引號內的任何匹配項,並能夠在匹配項上進行分割。請注意,解決方案仍然必須在字符串的其餘部分搜索parens,逗號和運算符。 當前正則表達式的版本:

tokenize_regex = re.compile(r'([\[\]\(\)\+\-\*/<>=!,])') 

比賽爲s是:

Match 1 
1. (
Match 2 
1. , 
Match 3 
1. , 
Match 4 
1. , 
Match 5 
1. > 
Match 6 
1. + 
Match 7 
1. , 
Match 8 
1. , 
Match 9 
1. , 
Match 10 
1. ) 

當我做:

tokens = Formula.tokenize_regex.split(self.formula) 
    print 'tokens: ' + str(tokens) 

它返回:

tokens: [u'MY_FUNC', u'(', u'AVG', u',', u' WFC US EQUITY', u',', u' WFC US EQUITY', u',', u' "', u'>', u'', u'+', u'3%"', u',', u' 1', u',', u'1', u',', u'7', u')', u''] 

但我需要d它排除在報價的數量,所以比賽應該是:

Match 1 
1. (
Match 2 
1. , 
Match 3 
1. , 
Match 4 
1. , 
Match 5 
1. , 
Match 6 
1. , 
Match 7 
1. , 
Match 8 
1. ) 

和令牌應該是:

tokens: [u'MY_FUNC', u'(', u'AVG', u',', u' WFC US EQUITY', u',', u' WFC US EQUITY', u',', u'">+3%"', u',', u' 1', u',', u'1', u',', u'7', u')', u''] 
+0

決定什麼是「內部」行情是很難用正則表達式。最好的辦法可能是使用正則表達式在預處理步驟中連續刪除引號內的所有內容,但即使嵌套引號也可能造成問題。 –

+0

不要在這種情況下嘗試使用're.split',嘗試爲're構建一個模式。findall',它更簡單,更高效。 –

+0

沒關係,如果它嵌套引號中斷。 – user1387717

回答

0

re.split不是一個乾淨的方式做標記化。在re的文檔中有一個recipe,它可以更好地爲您服務。基本上,你首先爲每個詞法類型編寫一個正則表達式。例如:

lexical_types = [ 
    ('QUOTED_CONTENT', r'"[^"]*?"'), 
    ('PAREN', r'[()]'), 
    ('OPERATOR', r'[-+<>]'), 
    ('COMMA', r','), 
    ('IDENTIFIER', r'[A-Z_][ A-Z_]*'), # our identifier can have spaces in it 
    # ... 
] 

然後你做一個高手的正則表達式了這些:

groups = ('(?P<{}>{})'.format(ltype, regex) for ltype, regex in lexical_types) 
tokenizer = re.compile('|'.join(groups)) 

然後,你將要記號化,以tokenizer.finditer字符串:

s = 'MY_FUNC(AVG, WFC US EQUITY, WFC US EQUITY, ">+3%", 1,1,7)' 
token_iter = tokenizer.finditer(s) # an iterator 

現在,如果你迭代通過token_iter,你將得到一串匹配對象,它包含你可能想要知道的關於字符串的所有信息(詞法上,就是這樣)。你可能想要做的是根據它的詞法類型來處理每個匹配對象。爲了演示,讓我們打印出來的詞彙類型,匹配的字符串,字符串相匹配的位置:

for token in token_iter: 
    ltype = token.lastgroup # lexical type of the token 
    print(ltype, token.group(ltype), token.span(ltype), sep=' ') 

輸出

IDENTIFIER MY_FUNC (0, 7) 
PAREN ( (7, 8) 
IDENTIFIER AVG (8, 11) 
COMMA , (11, 12) 
IDENTIFIER WFC US EQUITY (13, 26) 
COMMA , (26, 27) 
IDENTIFIER WFC US EQUITY (28, 41) 
COMMA , (41, 42) 
QUOTED_CONTENT ">+3%" (43, 49) 
COMMA , (49, 50) 
COMMA , (52, 53) 
COMMA , (54, 55) 
PAREN ) (56, 57) 

注:編譯主正則表達式時,你必須確保優先級較高的模式出現在優先級較低的模式之前。所以引用應該放在一切之前。由兩個字符組成的操作符(如!=)應在由一個字符組成的那些字符之前。

而且這種格局將處理單引號和雙引號:

r"""(?:'[^']*?'|"[^"]*?")""" # grouped for readability 
+0

但後來我真的不能在它上面分割 – user1387717

+0

@ user1387717哦,您需要*將引用的字符串保存爲標記嗎?對不起,我錯過了。那麼你可能需要'finditer'。我將編輯答案。 – gil

+0

標識符似乎沒有包含數字?爲什麼這對我的例子有效? – user1387717