正则表达式在字符串中匹配单词两次

2 投票
2 回答
1176 浏览
提问于 2025-04-17 23:53

我想找到一种方法,能够检测到字符串中任何全大写单词(或者它的部分)出现两次的位置。以下是一些例子——我想检测到的部分用粗体标出:

  • 00004 ADC SOME RANDOM WORDS ADC 其他无关字符
  • 02 SOME CANIT CAN 其他无关的200
  • 399 ADC0 FLAG ADC0 更多单词 adc

我现在有的(在网上的正则表达式解析器上看起来有效)是这个:

p = re.compile('( [A-Z]{2,}[A-Z0-9]*).*(\1)')
match = p.search('0x0000 ADC asdf ADC')
print(match)

我尝试了不同的空格变体等等,但这导致匹配结果为None。有没有什么提示可以告诉我这个正则表达式哪里出错了?

2 个回答

1

这里说的是用法,应该是\\1而不是\1

p = re.compile('( [A-Z]{2,}[A-Z0-9]*).*(\\1)')
2

在定义正则表达式模式时,建议使用原始字符串。具体可以参考这个讨论的第二和第三段,以及原始字符串表示法的解释。在你的例子中,'\1'被解释成了单个字符chr(1)

In [173]: '\1'
Out[173]: '\x01'

In [181]: list('\1')
Out[181]: ['\x01']

而你其实想要的是两个字符,一个反斜杠和一个数字1:

In [180]: list(r'\1')
Out[180]: ['\\', '1']

In [176]: p = re.compile(r'( [A-Z]{2,}[A-Z0-9]*).*(\1)')

In [177]: p.search('0x0000 ADC asdf ADC')
Out[177]: <_sre.SRE_Match at 0xb439770>

另外,如果你想找到尽可能多的这种模式,建议使用非贪婪模式.*?,而不是.*

In [195]: [(match.start(), match.end()) for match in re.finditer(r'\b([A-Z]{2,}[A-Z0-9]*).*?(\1)', '0x0000 ADC asdf ADC0 ADC ADC0')]
Out[195]: [(7, 19), (21, 28)]

撰写回答