【问题标题】:Regular Expression which matches two duplicate consecutive characters within string but not three or more. Should match if both 'aa' and 'bbb' exist匹配字符串中两个重复的连续字符但不匹配三个或更多的正则表达式。如果 'aa' 和 'bbb' 都存在则应该匹配
【发布时间】:2022-01-05 03:04:53
【问题描述】:

我最初的问题因重复而被关闭。我不同意它是重复的,因为这是查看正则表达式语法的不同用例。我试图在下面澄清我的问题。

是否可以创建一个正则表达式来匹配字符串中的两个重复的连续字符(在本例中为小写字母),但如果任一侧有相同的字符,则不匹配字符串的一部分。例如匹配 'aa' 但不匹配 'aaa''aaaa'

另外:

  • 虽然我使用的是 Python 3.10,但我正在尝试在不使用外部模块提供的附加功能的情况下使用“标准”正则表达式语法来确定这是否可行。例如使用 Python,这意味着使用标准库中的 're' 模块的解决方案。

  • 如果有 3 个或更多重复的连续字符,如果字符串的其他地方有两个重复的连续字符,则字符串应该仍然匹配。例如匹配'aa',即使'bbb' 存在于字符串中的其他位置。

  • 如果两个重复的连续字符出现在字符串的开头或结尾,字符串也应该匹配。

  • 如果特定长度有所不同,我的示例是 16 个字符串。

示例:

ffumlmqwfcsyqpss 应该匹配 'ff''ss'

zztdcqzqddaazdjp 应该匹配 'zz''dd''aa'

urrvucyrzzzooxhx 应该匹配 'rr''oo',即使'zzz' 存在于字符串中。

zettygjpcoedwyio 应该匹配 'tt'

dtfkgggvqadhqbwb 应该不匹配 'ggg'

rwgwbwzebsnjmtln 应该不匹配

我最初尝试过的

([a-z])\1(?!\1) 否定第三个重复字符,但这只是将匹配移动到重复字符串的末尾。

在开始时使用负环视来补偿匹配,但我认为我正在造成某种永远不会匹配的循环。

>>>import re

>>>re.search(r'([a-z])\1(?!\1)', 'dtfkgggvqadhqbwb')
<re.Match object; span=(5, 7), match='gg'> # should not match as 'gg' ('[gg]g' or 'g[gg]') 

当前提供的解决方案不符合描述的标准。

总结

到目前为止,唯一有效的答案是 Wiktor Stribiżew 的,但这使用了外部“正则表达式”模块的 (*SKIP) 函数。使用“标准”正则表达式语法是否无法解决?

【问题讨论】:

  • 原帖中使用的措辞是'它更方便'使用带有附加功能的regex模块,而不是没有它就不可能 匹配字符串。所以不可能使用 standard 正则表达式语法来匹配条件?我正在尝试学习正则表达式,所以对确认这一点非常感兴趣。
  • 好的,让我们用另一个答案更新线程。

标签: python regex regex-lookarounds


【解决方案1】:

您可以使用以下正则表达式模式:

^(?![a-z]*([a-z])\1{2,})[a-z]*([a-z])\2[a-z]*$

Demo

这个模式说匹配:

^                        start of the string
(?![a-z]*([a-z])\1{2,})  same letter does not occur 3 times or more
[a-z]*                   zero or more letters
([a-z])                  capture a letter
\2                       which is followed by the same letter
[a-z]*                   zero or more letters
$                        end of the string

【讨论】:

  • 此解决方案 nearly works 但如果 'aa''bbb' 都存在于同一字符串中,则不匹配。例如由于'zzz',它与'urrvucyrzzzooxhx' 中的'rr' 不匹配。我已经编辑了我原来的问题,试图让这个要求更清楚。是否可以调整此解决方案以满足此要求?我认为当前形式的负前瞻 (?![a-z]*([a-z])\1{2,}) 的使用需要以某种方式进行更改?
【解决方案2】:

在 Python re 中,为此任务创建正确的正则表达式的主要问题是,您需要在使用对组的反向引用之前定义捕获组,并且负向后视通常放置在捕获的模式之前。此外,regex101.com Python 测试选项并不总是反映re 库中的当前事务状态,它会使用户感到困惑,例如“此令牌不能在后视中使用,因为要么使它非固定宽度或干扰模式匹配“当它在(?&lt;!\1) 中看到\1 时,而Python 从v3.5 开始允许这样做对于固定长度的组。 p>

你可以在这里使用的模式是

(.)(?<!\1.)\1(?!\1)

请参阅regex demo

详情

  • (.) - 捕获组 1:任何单个字符(如果使用 re.DOTALL,即使是换行符)
  • (?&lt;!\1.) - 如果有与第 1 组中捕获的相同字符,然后是任何单个字符(我们可以在此处使用 \1 而不是 .,它会立即工作,则匹配失败)当前位置的左侧
  • \1 - 与第 1 组中的字符相同
  • (?!\1) - 如果在当前位置的右侧有与第 1 组中相同的字符,则匹配失败。

Python test

import re
tests ={'ffumlmqwfcsyqpss': ['ff','ss'],
    'zztdcqzqddaazdjp': ['zz','dd', 'aa'],
    'urrvucyrzzzooxhx': ['rr','oo'],
    'zettygjpcoedwyio': ['tt'],
    'dtfkgggvqadhqbwb': [],
    'rwgwbwzebsnjmtln': []
}


for test, answer in tests.items():
    matches = [m.group() for m in re.finditer(r'(.)(?<!\1.)\1(?!\1)', test, re.DOTALL)]
    if matches:
        print(f"Matches found in '{test}': {matches}. Is the answer expected? {set(matches)==set(answer)}.")
    else:
        print(f"No match found in '{test}'. Is the answer expected? {set(matches)==set(answer)}.")

输出:

Matches found in 'ffumlmqwfcsyqpss': ['ff', 'ss']. Is the answer expected? True.
Matches found in 'zztdcqzqddaazdjp': ['zz', 'dd', 'aa']. Is the answer expected? True.
Matches found in 'urrvucyrzzzooxhx': ['rr', 'oo']. Is the answer expected? True.
Matches found in 'zettygjpcoedwyio': ['tt']. Is the answer expected? True.
No match found in 'dtfkgggvqadhqbwb'. Is the answer expected? True.
No match found in 'rwgwbwzebsnjmtln'. Is the answer expected? True.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    相关资源
    最近更新 更多