【问题标题】:Python RegEx using re.sub with multiple patternsPython RegEx 使用具有多种模式的 re.sub
【发布时间】:2015-11-15 19:39:12
【问题描述】:

如果倒数第二个元音(从末尾开始)前面有另一个元音,我正在尝试使用 Python RegEx re.sub 删除一个单词的倒数第二个元音 [aeiou] 之前的冒号。

所以冒号必须在从词尾算起的第 3 和第 4 个元音之间。

所以给出的第一个例子会像这样分解w4:32ny1h

we:aanyoh > weaanyoh    # w4:32ny1h
hiru:atghigu > hiruatghigu
yo:ubeki > youbeki

下面是我尝试使用的 RegEx 语句,但我无法让它工作。

word = re.sub(ur"([aeiou]):([aeiou])(([^aeiou])*([aeiou])*([aeiou])([^aeiou])*([aeiou]))$", ur'\1\2\3\4', word)

【问题讨论】:

  • 所以你基本上搜索两个由冒号连接的元音?
  • 冒号必须位于从词尾算起的第 3 和第 4 个元音之间。所以给出的第一个例子会像这样分解 w4:32ny1h。
  • 很高兴指定 :) 在解密您的模式后想到这一点 :)
  • 是的,你是对的,我在问题中添加了这个:)
  • wef:fewee 呢?冒号在倒数第三个元音之前,前面有一个冒号,后面有两个元音。它满足您的描述,但不满足您的代码。

标签: python regex


【解决方案1】:

你不是有太多括号(和其他额外的东西)吗?:

word = re.sub(ur"([aeiou]):(([aeiou][^aeiou]*){3})$", ur'\1\2', word)

【讨论】:

  • 这不会确保冒号后的第一个字符是元音,请参阅我的回答。
  • [^aeiou] 匹配空格、换行符、其他冒号和标点符号。
【解决方案2】:

不确定是否要完全忽略辅音;这个正则表达式会。其他方面类似于 Jeff 的。

import re

tests = [
    'we:aanyoh',
    'hiru:atghigu',
    'yo:ubeki',
    'yo:ubekiki',
    'yo:ubek'
]

for word in tests:
    s = re.sub(r'([^aeiou]*[aeiou][^aeiou]*):((?:[^aeiou]*[aeiou]){3}[^aeiou]*)$', r'\1\2', word)
    print '{} > {}'.format(word, s)

【讨论】:

  • [^aeiou] 匹配空格、换行符、其他冒号和标点符号。
【解决方案3】:

您声明您的目标是一个单词而不是一行,因此首先将锚点设置为仅处理单词​​:

\b[regex will go here]\b
^                      ^     assert a word boundary

接下来,冒号后面是[aeiou],冒号后面的部分还有两个[aeiou]。我假设不区分大小写?

(?i)(\b\w+[aeiou]):((?:[aeiou][^aeiou\s\W]*){3}\b)
                                   ^  match a character that is NOT vowel, space or not a 
                                         ^   \W=[^a-zA-Z0-9_]

Demo

(注意[^aeiou\W]的使用,它是辅音字母、数字和_,而不是其他字符Demo。)

Python 演示:

import re

tests={
    'matches':[
        'we:aanyoh',
        'hiru:atghigu',
        'yo:ubeki'
        ],
    'no match':[
        'wz:ubeki',
        'we:a anyoh',
        'yo:ubek',
        'hiru:atghiguu'
    ]    
}

for k, v in tests.items():
    print k
    for e in v:
        s=re.sub(r'(?i)(\b\w+[aeiou]):((?:[aeiou][^aeiou\s\W]*){3}\b)', r'\1\2', e)
        print '\t{} > {}'.format(e, s)

打印:

matches
    we:aanyoh > weaanyoh
    hiru:atghigu > hiruatghigu
    yo:ubeki > youbeki
no match
    wz:ubeki > wz:ubeki
    we:a anyoh > we:a anyoh
    yo:ubek > yo:ubek
    hiru:atghiguu > hire:atghiguu

这只会处理带有单个冒号的单词。如果要匹配具有多个冒号但具有相同模式的单词,请将 LH 模式更改为具有包含冒号和非 \b 的锚点的字符类。

示例:(?i)(^[\w:]+[aeiou]):((?:[aeiou][^aeiou\s\W]*){3}\b)

【讨论】:

    【解决方案4】:

    它应该与这个一起工作:

    word = re.sub(ur"(?<=[aeiou]):(?=[aeiou]([^aeiou]*[aeiou]){2}[^aeiou]*$)", ur'', word)
    

    在此处查看示例:https://regex101.com/r/kA8xH3/2

    请注意,我只捕获冒号并将其替换为空字符串,而不是捕获组并将它们连接起来。

    Tt 检查冒号组合,然后提前检查是否有 2 个额外的元音(可能还有辅音)。它还允许在末尾添加辅音,但确保$ 中不再有元音

    【讨论】:

    • [^aeiou]*$ 星号说它可以是0或更多,所以它可以以0个辅音结尾,这意味着一个元音
    • 如果有空格或其他字符,这将失败:) 只是想变得更平,哈哈
    • @lonut 在哪里?我使用[^aeiou],所以第二个应该包含空格和特殊字符,不是吗?如果我的有,你也会的,对吧? ;)
    • :) 现在怎么样? :)
    【解决方案5】:

    这样就可以了:

        word = re.sub(ur"([aeiou]):([aeiou])([^\Waeiou]*[aeiou][^\Waeiou]*[aeiou][^\Waeiou]*)$", ur'\1\2\3', word)
    

    http://www.phpliveregex.com/p/dCa

    【讨论】:

    • 那行不通。在您的表达中,冒号后面必须有 2 个元音,这意味着不会捕获像第二个和第三个示例这样的内容
    • 是的,我看到了。但是你有([aeiou]):([aeiou])(([aeiou],它表示必须连续有 3 个元音,第一个和第二个元音之间有一个冒号
    • 是的,:([aeiou])(([aeiou][^aeiou]*){2}) 之间是什么?不允许使用其他辅音,因此不允许使用 dsa:adaa 之类的内容
    【解决方案6】:

    Roundup(我使用大写元音来指示替换应该在单词中的哪个位置进行)。如果您希望我添加其他测试字符串,请告诉我。

    import re
    
    strings = [
        'wE:aanyoh',
        'hirU:atghigu',
        'yO:ubeki',
    
        'xE:aaa',
        'xx:aaa',
        'xa:aaaxA:aaa',
        'xa:aaaxA:aaaxx',
        'xa:aaaxA:aaxax',
        'a:aaaxA:aaxax',
        'e:aeixA:aexix',
    ]
    
    
    pattern = r"""
        (
            .*
            [aeiou]
        )
        :
        (
            [aeiou]
            .*?
            [aeiou]
            .*?
            [aeiou]
        )
    """
    
    template = "{:>15}: {}"
    for string in strings:
        print(
            template.format('original', string)
        )
    
        print(template.format('Alexander:', 
            re.sub(ur"(?<=[aeiou]):(?=[aeiou]([^aeiou]*[aeiou]){2}[^aeiou]*$)", ur'', string, flags=re.I)
        ))
    
        print(template.format('lonut:', 
            re.sub(ur"([aeiou]):([aeiou])([^\Waeiou]*[aeiou][^\Waeiou]*[aeiou][^\Waeiou]*)$", ur'\1\2\3', string, flags=re.I)
        ))
    
        print(template.format('Tom Zych:', 
            re.sub(r'([^aeiou]*[aeiou][^aeiou]*):((?:[^aeiou]*[aeiou]){3}[^aeiou]*)$', r'\1\2', string, flags=re.I)
        ))
    
        print(template.format('Jeff Y:', 
            re.sub(ur"([aeiou]):(([aeiou][^aeiou]*){3})$", ur'\1\2', string, flags=re.I)
        ))
    
        print(template.format('7stud:', 
            re.sub(pattern, r'\1\2', string, count=1, flags=re.X|re.I)
        ))
    
        print("\n")
    

           original: wE:aanyoh
         Alexander:: wEaanyoh
             lonut:: wEaanyoh
          Tom Zych:: wEaanyoh
            Jeff Y:: wEaanyoh
             7stud:: wEaanyoh
    
    
           original: hirU:atghigu
         Alexander:: hirUatghigu
             lonut:: hirUatghigu
          Tom Zych:: hirUatghigu
            Jeff Y:: hirUatghigu
             7stud:: hirUatghigu
    
    
           original: yO:ubeki
         Alexander:: yOubeki
             lonut:: yOubeki
          Tom Zych:: yOubeki
            Jeff Y:: yOubeki
             7stud:: yOubeki
    
    
           original: xE:aaa
         Alexander:: xEaaa
             lonut:: xEaaa
          Tom Zych:: xEaaa
            Jeff Y:: xEaaa
             7stud:: xEaaa
    
    
           original: xx:aaa
         Alexander:: xx:aaa
             lonut:: xx:aaa
          Tom Zych:: xx:aaa
            Jeff Y:: xx:aaa
             7stud:: xx:aaa
    
    
           original: xa:aaaxA:aaa
         Alexander:: xa:aaaxAaaa
             lonut:: xa:aaaxAaaa
          Tom Zych:: xa:aaaxAaaa
            Jeff Y:: xa:aaaxAaaa
             7stud:: xa:aaaxAaaa
    
    
           original: xa:aaaxA:aaaxx
         Alexander:: xa:aaaxAaaaxx
             lonut:: xa:aaaxAaaaxx
          Tom Zych:: xa:aaaxAaaaxx
            Jeff Y:: xa:aaaxAaaaxx
             7stud:: xa:aaaxAaaaxx
    
    
           original: xa:aaaxA:aaxax
         Alexander:: xa:aaaxAaaxax
             lonut:: xa:aaaxAaaxax
          Tom Zych:: xa:aaaxAaaxax
            Jeff Y:: xa:aaaxAaaxax
             7stud:: xa:aaaxAaaxax
    
    
           original: a:aaaxA:aaxax
         Alexander:: a:aaaxAaaxax
             lonut:: a:aaaxAaaxax
          Tom Zych:: a:aaaxAaaxax
            Jeff Y:: a:aaaxAaaxax
             7stud:: a:aaaxAaaxax
    
    
           original: e:aeixA:aexix
         Alexander:: e:aeixAaexix
             lonut:: e:aeixAaexix
          Tom Zych:: e:aeixAaexix
            Jeff Y:: e:aeixAaexix
             7stud:: e:aeixAaexix
    

    【讨论】:

    • 在你的模式中 - [aeiou].*?[aeiou].*?[aeiou] - 元音后跟什么?那不允许有数百个元音吗?您的测试用例似乎只测试冒号后文本中恰好有三个元音的情况。
    • @TessellatingHeckler,是的。 :(
    • 我不明白你为什么要比较其他答案。你介意解释一下有什么区别吗?
    • @7stud 在这种情况下,所有答案都会产生相同的结果,这就是我要问的原因(这里没有“你好”与“再见”的案例)。我建议对您的模式失败的字符串a:eiouaeioua:exxx io 进行测试。另外,我不明白你为什么遗漏了 dawg 的答案,我认为这应该是这个问题的公认答案。
    • @Mariano,假设对于一个示例字符串,一个答案产生结果“你好”,另一个答案产生结果“再见”,你会怎么做?例如,THeckler 提出了一个思想实验,这就像添加一个额外的测试字符串,我的答案基本上产生了“你好”,而所有其他答案都产生了“再见”。如果每个人都在测试不同的字符串,那么您无法知道是否所有答案都适用于所有测试过的字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 2019-02-22
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多