我希望使用正则表达式将单词分成(vowels, not_vowels, more_vowels)
组,使用标记确保每个单词以元音开头和结尾。
import re
MARKER = "~"
VOWELS = {"a", "e", "i", "o", "u", MARKER}
word = "dog"
if word[0] not in VOWELS:
word = MARKER+word
if word[-1] not in VOWELS:
word += MARKER
re.findall("([%]+)([^%]+)([%]+)".replace("%", "".join(VOWELS)), word)
在这个例子中我们得到:
[('~', 'd', 'o')]
问题是我希望比赛重叠 - 最后一组元音应该成为下一场比赛的第一组。如果我们按如下方式替换正则表达式,那么前瞻性可能会出现这种情况:
re.findall("([%]+)([^%]+)(?=[%]+)".replace("%", "".join(VOWELS)), word)
我们得到:
[('~', 'd'), ('o', 'g')]
这意味着我们正在匹配我想要的东西。但是,它现在不返回最后一组元音。我想要的输出是:
[('~', 'd', 'o'), ('o', 'g', '~')]
我觉得这应该是可能的(如果正则表达式可以检查第二组元音,我认为没有理由它不能返回它们),但我找不到任何办法超越蛮力方法,在我拥有它们之后循环结果,并将下一个匹配的第一个字符追加到最后一个匹配,并将字符串的最后一个字符追加到最后一个匹配。有没有更好的方法可以做到这一点?
两个可行的方法是捕获前瞻值,或者在捕获值时不消耗匹配上的文本 - 我找不到任何方法。
答案 0 :(得分:8)
我发布后才发现:
re.findall("([%]+)([^%]+)(?=([%]+))".replace("%", "".join(VOWELS)), word)
在前瞻中添加一对额外的括号意味着它本身就成了捕获。
我觉得这很晦涩且很难找到 - 我不确定是否其他所有人都发现这一点很明显,但希望我所在的其他人在将来更容易发现这一点。
答案 1 :(得分:2)
我不会尝试让正则表达式引擎这样做;我会将字符串拆分为辅音和元音块,然后生成重叠结果。这样,你实际上也不需要破解标记,假设当单词实际上没有或以元音结尾时,''
作为“元音”部分是可以的。
def overlapping_matches(word):
pieces = re.split('([^aeiou]+)', word)
# There are other ways to do this; I'm kinda showing off
return zip(pieces[:-2], pieces[1:-1], pieces[2:])[::2]
overlapping_matches('dog') # [('', 'd', 'o'), ('o', 'g', '')]
(如果word
仅包含元音,这仍然会失败,但如果有必要,这会被轻易纠正。)