Python正则表达式,在引号中排除匹配

时间:2016-02-25 22:26:54

标签: python regex

我有这个字符串:

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

这个正则表达式搜索parens,逗号和简单的运算符。我需要排除双引号内的任何匹配,并能够在匹配上拆分。请注意,解决方案仍必须在字符串的其余部分中搜索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'']

但是我需要它来排除引号中的数量,所以匹配应该是:

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'']

1 个答案:

答案 0 :(得分:1)

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,你将获得一个匹配对象流,其中包含你可能想知道的关于字符串的所有内容(词汇方式,即)。您可能想要做的是根据其词法类型处理每个匹配对象。对于demo,让我们打印出词法类型,匹配的字符串以及匹配的字符串的位置:

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