如何制作文章微调器正则表达式?

y2k*_*y2k 2 .net c# python article spinner

让我们说我有以下几点:

{{Hello | Hi | Hey} {world | earth} | {再见|告别} {noobs | n3wbz | n00blets}}

我希望它变成以下任何一种:

Hello world 
Goodbye noobs 
Hi earth
farewell n3wbz 
// etc.
Run Code Online (Sandbox Code Playgroud)

注意嵌套"旋转"语法的方式.对于我们所知道的,它可以嵌套十亿层深.

我可以很容易地做到这一点,除非他们像上面的例子一样嵌套我的正则表达式混乱并且结果不正确.

有人可以用.NET语言或Python显示一个例子吗?

Red*_*yph 5

使用re.subn的简单方法,它也可以接受函数而不是替换字符串:

import re
from random import randint

def select(m):
    choices = m.group(1).split('|')
    return choices[randint(0, len(choices)-1)]

def spinner(s):
    r = re.compile('{([^{}]*)}')
    while True:
        s, n = r.subn(select, s)
        if n == 0: break
    return s.strip()
Run Code Online (Sandbox Code Playgroud)

它只是取代它遇到的所有最深的选择,然后迭代直到没有选择.subn返回一个元组,其中包含结果和多少次替换,这样便于检测处理结束.

我的版本select()可以被使用的Bobince取代,random.choice()如果你只想坚持随机选择器,它会更优雅.如果你想建立一个选择的树,你可以扩展上面的功能,但你需要全局变量来跟踪你在哪里,所以移动功能集成到一类是有意义.这只是一个暗示,我不会发展这个想法,因为它不是真正的原始问题.

最后请注意,r.subn(select, s, re.U)如果需要unicode字符串,则应该使用(s = u"{...}")

例:

>>> s = "{{Hello|Hi|Hey} {world|earth} | {Goodbye|farewell} {noobs|n3wbz|n00blets}}"
>>> print spinner(s)
'farewell n3wbz'
Run Code Online (Sandbox Code Playgroud)

编辑:替换sub通过subn避免无限循环(感谢Bobince指出来),并使其更有效率,并更换{([^{}]+)}{([^{}]*)}提取空的大括号为好.这应该使格式不良的模式更加健壮.

对于那些喜欢尽可能多地放在一条线上的人(我个人不鼓励):

def spin(s):
    while True:
        s, n = re.subn('{([^{}]*)}',
                       lambda m: random.choice(m.group(1).split("|")),
                       s)
        if n == 0: break
    return s.strip()
Run Code Online (Sandbox Code Playgroud)