Python正则表达式字符串扩展

时间:2013-11-19 01:13:02

标签: python regex string

假设我有以下字符串:

trend  = '(A|B|C)_STRING'

我想将其扩展为:

A_STRING
B_STRING
C_STRING

OR条件可以是字符串中的任何位置。即STRING_(A|B)_STRING_(C|D)

将扩展为

STRING_A_STRING_C
STRING_B_STRING C
STRING_A_STRING_D
STRING_B_STRING_D

我还想介绍空条件的情况:

(|A_)STRING将扩展为:

A_STRING
STRING

这是我到目前为止所尝试的内容:

def expandOr(trend):
    parenBegin = trend.index('(') + 1
    parenEnd = trend.index(')')
    orExpression = trend[parenBegin:parenEnd]
    originalTrend = trend[0:parenBegin - 1]
    expandedOrList = []

    for oe in orExpression.split("|"):
        expandedOrList.append(originalTrend + oe)

但这显然不起作用。

使用正则表达式有没有简单的方法呢?

4 个答案:

答案 0 :(得分:4)

这是一个非常干净的方式。你会很开心地弄清楚它是如何工作的: - )

def expander(s):
    import re
    from itertools import product
    pat = r"\(([^)]*)\)"
    pieces = re.split(pat, s)
    pieces = [piece.split("|") for piece in pieces]
    for p in product(*pieces):
        yield "".join(p)

然后:

for s in ('(A|B|C)_STRING',
          '(|A_)STRING',
          'STRING_(A|B)_STRING_(C|D)'):
    print s, "->"
    for t in expander(s):
        print "   ", t

显示:

(A|B|C)_STRING ->
    A_STRING
    B_STRING
    C_STRING
(|A_)STRING ->
    STRING
    A_STRING
STRING_(A|B)_STRING_(C|D) ->
    STRING_A_STRING_C
    STRING_A_STRING_D
    STRING_B_STRING_C
    STRING_B_STRING_D

答案 1 :(得分:3)

import exrex
trend  = '(A|B|C)_STRING'
trend2 = 'STRING_(A|B)_STRING_(C|D)'

>>> list(exrex.generate(trend))
[u'A_STRING', u'B_STRING', u'C_STRING']

>>> list(exrex.generate(trend2))
[u'STRING_A_STRING_C', u'STRING_A_STRING_D', u'STRING_B_STRING_C', u'STRING_B_STRING_D']

答案 2 :(得分:1)

我会这样做以提取组:

def extract_groups(trend):
    l_parens = [i for i,c in enumerate(trend) if c == '(']
    r_parens = [i for i,c in enumerate(trend) if c == ')']
    assert len(l_parens) == len(r_parens)
    return [trend[l+1:r].split('|') for l,r in zip(l_parens,r_parens)]

然后,您可以使用itertools.product评估这些提取组的产品:

expr = 'STRING_(A|B)_STRING_(C|D)'
from itertools import product
list(product(*extract_groups(expr)))
Out[92]: [('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D')]

现在只是把它们拼接回原始表达的问题。我将使用re:)

#python3.3+
def _gen(it):
    yield from it

p = re.compile('\(.*?\)')

for tup in product(*extract_groups(trend)):
    gen = _gen(tup)
    print(p.sub(lambda x: next(gen),trend))

STRING_A_STRING_C
STRING_A_STRING_D
STRING_B_STRING_C
STRING_B_STRING_D

可能有一种更易读的方式让re.sub顺序替换迭代中的东西,但这就是我的头脑。

答案 3 :(得分:0)

使用sre_yield module很容易实现:

>>> import sre_yield
>>> trend  = '(A|B|C)_STRING'
>>> strings = list(sre_yield.AllStrings(trend))
>>> print(strings)
['A_STRING', 'B_STRING', 'C_STRING']
<块引用>

sre_yield 的目标是有效地生成可以匹配给定正则表达式的所有值,或者有效地计算可能的匹配... sre_parse 模块内部使用的东西),并根据需要构造链式/重复迭代器。可能会有重复的结果,具体取决于您的输入字符串——这些是 re 未优化的情况。