gpt4 book ai didi

python - 正则表达式在字符串开头未匹配

转载 作者:行者123 更新时间:2023-11-28 17:59:36 26 4
gpt4 key购买 nike

我有 as 和 bs 的字符串。我想提取所有重叠的子序列,其中一个子序列是由任意数量的 b 包围的单个 a。这是我写的正则表达式:

import re

pattern = """(?= # inside lookahead for overlapping results
(?:a|^) # match at beginning of str or after a
(b* (?:a) b*) # one a between any number of bs
(?:a|$)) # at end of str or before next a
"""
a_between_bs = re.compile(pattern, re.VERBOSE)

它似乎按预期工作,除非字符串中的第一个字符是 a,在这种情况下会遗漏此子序列:

a_between_bs.findall("bbabbba")
# ['bbabbb', 'bbba']
a_between_bs.findall("abbabb")
# ['bbabb']

我不明白发生了什么。如果我更改潜在匹配的开始顺序,结果也会发生变化:

pattern = """(?=
(?:^|a) # a and ^ swapped
(b* (?:a) b*)
(?:a|$))
"""
a_between_bs = re.compile(pattern, re.VERBOSE)

a_between_bs.findall("abbabb")
# ['abb']

我原以为这是对称的,因此也可能会遗漏以 a 结尾的字符串,但事实并非如此。这是怎么回事?

编辑:

我假设上面玩具示例的解决方案会转化为我的全部问题,但事实似乎并非如此,所以我现在正在详细说明(对此感到抱歉)。我正在尝试从转录的单词中提取“音节”。 “音节”是元音或双元音,其前后有任意数量的辅音。这是我提取它们的正则表达式:

vowels = 'æɑəɛiɪɔuʊʌ'
diphtongues = "|".join(('aj', 'aw', 'ej', 'oj', 'ow'))
consonants = 'θwlmvhpɡŋszbkʃɹdnʒjtðf'

pattern = f"""(?=
(?:[{vowels}]|^|{diphtongues})
([{consonants}]* (?:[{vowels}]|{diphtongues}) [{consonants}]*)
(?:[{vowels}]|$|{diphtongues})
)
"""
syllables = re.compile(pattern, re.VERBOSE)

棘手的一点是双元音以辅音(j 或 w)结尾,我不想将其包含在下一个音节中。所以用双重否定替换第一个非捕获组 (?<![{consonants}])不起作用。我试图用积极的前瞻性代替该组 (?<=[{vowels}]|^|{diphtongues}) , 但正则表达式不会接受不同的长度(即使删除双元音也不起作用,显然 ^ 的长度不同)。

所以这是上面模式的问题案例:

syllables.findall('æbə')
# ['bə']
# should be: ['æb', 'bə']

编辑 2:我已经切换到使用正则表达式,它允许可变宽度的后视,从而解决了这个问题。令我惊讶的是,它甚至似乎比标准库中的 re 模块更快。不过,我仍然想知道如何使它与 re 模块一起工作。 (:

最佳答案

我建议用双重否定来解决这个问题:

(?=         # inside lookahead for overlapping results
(?<![^a]) # match at beginning of str or after a
(b*ab*) # one a between any number of bs
(?![^a]) # at end of str or before next a
)

参见 regex demo

请注意,我用lookarounds 替换了grouping 结构:(?:a|^)(?<![^a])(?:a|$)(?![^a]) .后者并不重要,但前者在这里非常重要。

(?:a|^)在外部先行模式匹配的开头 a或字符串的开头,以先到者为准。如果a在开始时,它被匹配并且当输入是abbabb时, 你得到 bbabb因为它与捕获组模式相匹配,并且紧随其后的是字符串位置的结尾。下一次迭代在第一个 a 之后开始,并且找不到任何匹配项,因为唯一的 a留在字符串中没有ab 之后

请注意 order of alternative matters .如果更改为 (?:^|a) ,匹配从字符串的开头开始,b*匹配空字符串,ab*抢第一abbabbabb , 因为有 a紧接着,你会得到 abb作为比赛。在第一个 a 之后无法匹配任何内容.

关于python - 正则表达式在字符串开头未匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56367503/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com