4

我希望使用正则表达式将单词分成几组(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', '~')]

我觉得这应该是可能的(如果正则表达式可以检查第二组元音,我看不出它不能返回它们的原因),但除了蛮力方法之外,我找不到任何方法,循环通过我拥有它们并将下一个匹配的第一个字符附加到最后一个匹配,并将字符串的最后一个字符附加到最后一个匹配之后的结果。有没有更好的方法可以做到这一点?

可行的两件事是捕获前瞻值,或者在捕获值的同时不消耗匹配中的文本-我也找不到任何方法。

4

2 回答 2

10

我是在发帖后才发现的:

re.findall("([%]+)([^%]+)(?=([%]+))".replace("%", "".join(VOWELS)), word)

在前瞻中添加一对额外的括号意味着它本身就是一个捕获。

我发现这非常晦涩难懂——我不确定是不是其他人都觉得这很明显,但希望我这个职位的其他人将来会更容易找到这一点。

于 2012-04-09T23:26:33.713 回答
3

我不会尝试让正则表达式引擎这样做;我会将字符串拆分为辅音和元音块,然后生成重叠的结果。这样,您实际上也不需要修改标记,假设您可以''在单词实际上不是元音或以元音结尾时作为“元音”部分。

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,但如果有必要,这会被简单地纠正。)

于 2012-04-10T00:28:50.857 回答