在Python中对同一字符串多次使用re.match()

5 投票
3 回答
10153 浏览
提问于 2025-04-16 13:47

我有一个正则表达式,用来找到 :ABC:`hello` 这种模式。下面是代码。

format =r".*\:(.*)\:\`(.*)\`"
patt = re.compile(format, re.I|re.U)
m = patt.match(l.rstrip())
if m:
    ...

当这一模式在一行中出现一次时,它运行得很好。但是在一个例子中,像这样 ":tagbox:`Verilog` :tagbox:`Multiply` :tagbox:`VHDL`",它只找到最后一个。

我该怎么才能找到这三个模式呢?

编辑

根据 Paul Z 的回答,我用下面的代码解决了这个问题。

format = r"\:([^:]*)\:\`([^`]*)\`"
patt = re.compile(format, re.I|re.U)
for m in patt.finditer(l.rstrip()):
    tag, value = m.groups()  
    print tag, ":::", value

结果

tagbox ::: Verilog
tagbox ::: Multiply
tagbox ::: VHDL

3 个回答

0

re.findall 或者更好的选择 regex.findall 可以用一行代码帮你完成这个任务:

import regex as re #or just import re
s = ":tagbox:`Verilog` :tagbox:`Multiply` :tagbox:`VHDL`"
format = r"\:([^:]*)\:\`([^`]*)\`"
re.findall(format,s)

结果是:

[('tagbox', 'Verilog'), ('tagbox', 'Multiply'), ('tagbox', 'VHDL')]
2

一个好的起点是re模块的文档。除了re.match(这个方法是从字符串的开头开始查找),还有re.findall(这个方法会找到所有不重叠的模式出现),以及编译后的RegexObjectmatchsearch方法,这两个方法都可以指定开始和结束的位置,以限制查找的字符串部分。还有split方法,它会根据模式把字符串分割成一个子字符串的列表。根据你想要的输出格式,这些方法中的某一个可能会对你有帮助。

9

是的,dcrosta建议你去看看re模块的文档,这个建议挺不错的,但我猜你其实想用的是finditer这个函数。试试这个:

format = r"\:(.*)\:\`(.*)\`"
patt = re.compile(format, re.I|re.U)
for m in patt.finditer(l.rstrip()):
    tag, value = m.groups()
    ....

你现在的解决方案总是找到最后一个匹配,因为最开始的.*会尽量多地匹配字符,直到找到一个有效的匹配(也就是最后一个)。顺便说一下,这样做可能会让你的程序变得非常慢,因为.*会先尝试匹配整个字符串,然后再一个字符一个字符地回退,直到剩下的表达式告诉它“这匹配得太多了,回去吧”。使用finditer应该会更高效。

撰写回答