Python正则表达式匹配具有重复辅音的单词

Python正则表达式匹配具有重复辅音的单词,python,regex,Python,Regex,首先,这是家庭作业。(我不能在标题中使用标签,并且底部的标签列表中没有显示任何作业,因此请让我知道我是否应该编辑与此相关的其他内容) 因此,我一直在阅读python文档并进行清理,找到了一些接近我想要的解决方案,但并不精确 我有一本字典,我把它读入一个字符串: a aa aabbaa ... z 我们正在对这些数据使用各种正则表达式模式。 这里的具体问题是返回与模式匹配的单词列表,而不是每个匹配中包含组的元组 例如: 给定此词典的子集,如: someword sommmmmeword some

首先,这是家庭作业。(我不能在标题中使用标签,并且底部的标签列表中没有显示任何作业,因此请让我知道我是否应该编辑与此相关的其他内容)

因此,我一直在阅读python文档并进行清理,找到了一些接近我想要的解决方案,但并不精确

我有一本字典,我把它读入一个字符串:

a
aa
aabbaa
...
z
我们正在对这些数据使用各种正则表达式模式。 这里的具体问题是返回与模式匹配的单词列表,而不是每个匹配中包含组的元组

例如:

给定此词典的子集,如:

someword
sommmmmeword
someworddddd
sooooomeword
我想返回:

['sommmmmword', 'someworddddd']
不是:

编辑:

我在上面这个例子背后的理由是,我想看看如何避免第二次忽略结果。这并不是说:

res = re.match(re.compile(r'pattern'), dictionary)
return [r[0] for r in res]
我特别想要一个机制,我可以只使用:

return re.match(re.compile(r'pattern'), dictionary)
我知道这听起来很傻,但我这样做是为了真正深入研究正则表达式。我在底部提到这一点

这就是我尝试过的:

# learned about back refs
r'\b([b-z&&[^eiou]])\1+\b' -> # nothing

# back refs were weird, I want to match something N times
r'\b[b-z&&[^eiou]]{2}\b' -> # nothing
在测试的某个地方,我注意到一个模式返回类似于
'\nsomeword'
的内容。我不知道它是什么,但如果我再次找到该模式,我会将其包含在这里,以确保完整性

# Maybe the \b word markers don't work how I think?
r'.*[b-z&&[^eiou]]{2}' -> # still nothing

# Okay lets just try to match something in between anything
r'.*[b-z&&[^eiou]].*' -> # nope

# Since its words, maybe I should be more explicit.
r'[a-z]*[b-z&&[^eiou]][a-z]*' -> # still nope

# Decided to go back to grouping.
r'([b-z&&[^eiou]])(\1)'  # I realize set difference may be the issue

# I saw someone (on SO) use set difference claiming it works
#  but I gave up on it...

# OKAY getting close
r'(([b-df-hj-np-tv-xz])(\2))' -> [('ll', 'l', 'l'), ...]

# Trying the the previous ones without set difference 
r'\b(.*(?:[b-df-hj-np-tv-xz]{3}).*)\b'  -> # returned everything (all words)

# Here I realize I need a non-greedy leading pattern (.* -> .*?)
r'\b(.*?(?:[b-df-hj-np-tv-xz]{3}).*)\b' ->  # still everything

# Maybe I need the comma in {3,} to get anything 3 or more
r'\b(.*?(?:[b-df-hj-np-tv-xz]{3,}).*)\b' ->  # still everything

# okay I'll try a 1 line test just in case
r'\b(.*?([b-df-hj-np-tv-xz])(\2{3,}).*)\b'  
    # Using 'asdfdffff' -> [('asdfdffff', 'f', 'fff')]
    # Using dictionary -> []  # WAIT WHAT?!
最后一个如何工作?也许没有3+个重复的辅音词?我正在学校服务器上使用
/usr/share/dict/cracklib small
,我想大概有50000个单词

我仍在努力,但任何建议都会很棒

有一件事我觉得很奇怪,那就是你不能引用一个未捕获的组。如果我只想输出完整的单词,我会使用(?:…)来避免捕获,但是我不能返回引用。显然,我可以留下捕获,循环结果,过滤掉多余的东西,但我绝对想用正则表达式来解决这个问题


也许有一种方法可以实现非捕获,但仍然允许反向引用?或者可能有一个完全不同的表达式我还没有测试过。

这里有几点需要考虑:

  • 使用
    re.findall
    获取所有结果,而不是
    re.match
    (仅搜索1个匹配项,且仅在字符串开头)

  • [b-z&&[^eiou]]
    是一个Java/ICU正则表达式,Python
    re
    不支持此语法。在Python中,您可以重新定义范围以跳过元音,也可以使用
    (?![eiou])[b-z]

  • 要避免元组中带有
    re.findall
    的“额外”值,请不要使用捕获组。如果需要反向引用,请使用
    re.finditer
    而不是
    re.findall
    并访问每个匹配项的
    .group()

  • 回到问题上来,如何使用回溯引用仍然获得整个比赛,以下是一个:


    当你努力完成作业后,可以在这里问一下家庭作业:)你能分享一下
    ['sommmmmmword','sommwordddddd']
    [('sommmword','mmmmmm',…),…]
    背后的逻辑吗?啊,是的,如果这看起来让人困惑的话,很抱歉。我输入了一个edit.1)使用
    re.findall
    获取所有结果,而不是
    re.match
    (只搜索1个匹配项,并且只在字符串开头)。2)
    [b-z&&[^eiou]]
    是一个Java/ICU正则表达式,Python
    re
    不支持此语法。3) 要避免元组中带有
    re.findall
    的“额外”值,请不要使用捕获组。如果您需要反向引用,请使用
    re.finditer
    而不是
    re.findall
    ,并访问每个匹配项的
    .group()
    。这就是您要查找的吗?啊,我使用的是fiindall,我只是输入了错误的示例。但我没有尝试finditer!我以为那只是芬德尔的发电机。我会在回家后测试一下!非常感谢。另外,作为一个旁注,我是否可以使用\1{N}而不将其分组,而不是显式地说“\1\1\1…”来收集匹配的N个副本?您可以使用带有反向引用(=量化反向引用)的量词,方式与任何原子相同:
    \1{4}
    。看见
    # Maybe the \b word markers don't work how I think?
    r'.*[b-z&&[^eiou]]{2}' -> # still nothing
    
    # Okay lets just try to match something in between anything
    r'.*[b-z&&[^eiou]].*' -> # nope
    
    # Since its words, maybe I should be more explicit.
    r'[a-z]*[b-z&&[^eiou]][a-z]*' -> # still nope
    
    # Decided to go back to grouping.
    r'([b-z&&[^eiou]])(\1)'  # I realize set difference may be the issue
    
    # I saw someone (on SO) use set difference claiming it works
    #  but I gave up on it...
    
    # OKAY getting close
    r'(([b-df-hj-np-tv-xz])(\2))' -> [('ll', 'l', 'l'), ...]
    
    # Trying the the previous ones without set difference 
    r'\b(.*(?:[b-df-hj-np-tv-xz]{3}).*)\b'  -> # returned everything (all words)
    
    # Here I realize I need a non-greedy leading pattern (.* -> .*?)
    r'\b(.*?(?:[b-df-hj-np-tv-xz]{3}).*)\b' ->  # still everything
    
    # Maybe I need the comma in {3,} to get anything 3 or more
    r'\b(.*?(?:[b-df-hj-np-tv-xz]{3,}).*)\b' ->  # still everything
    
    # okay I'll try a 1 line test just in case
    r'\b(.*?([b-df-hj-np-tv-xz])(\2{3,}).*)\b'  
        # Using 'asdfdffff' -> [('asdfdffff', 'f', 'fff')]
        # Using dictionary -> []  # WAIT WHAT?!
    
    import re
    s = """someword
    sommmmmeword
    someworddddd
    sooooomeword"""
    res =[x.group() for x in re.finditer(r"\w*([b-df-hj-np-tv-xz])\1\w*", s)]
    print(res)
    # => ['sommmmmeword', 'someworddddd']