使用re.match或re.search返回多个匹配结果

3

我正在将一些代码转换为Micropython,但遇到了一个特定的正则表达式问题。

在Python中,我的代码是:

import re

line = "0-1:24.2.1(180108205500W)(00001.290*m3)"
between_brackets = '\(.*?\)' 

brackettext  = re.findall(between_brackets, line) 
gas_date_str = read_date_time(brackettext[0])
gas_val      = read_gas(brackettext[1])

# gas_date_str and gas_val take the string between brackets 
# and return a value that can later be used

MicroPython仅实现了有限的re函数集

那么只使用可用的有限函数,我该如何实现相同的功能?

2个回答

4
你可以沿以下方式进行操作。在消耗字符串时,重复使用re.search。这里的实现使用了生成器函数:
import re

def findall(pattern, string):
    while True:
        match = re.search(pattern, string)
        if not match:
            break
        yield match.group(0)
        string = string[match.end():]

>>> list(findall(r'\(.*?\)', "0-1:24.2.1(180108205500W)(00001.290*m3)"))
['(180108205500W)', '(00001.290*m3)']

我喜欢代码的紧凑性和使用yield。 - Marc Wagner
值得一提的是,虽然match.end在核心MicroPython库中,但其实现因端口而异。例如,在PyCom板上...没有.end()。(截至今天) - Patrick
在玩弄micropython regex时,我错过了这个 - 所以这对我帮助很大!+1 - con

2
您可以使用re.search()编写一个方法,该方法返回所有匹配项的列表:
import re  

def find_all(regex, text):
    match_list = []
    while True:
        match  = re.search(regex, text)
        if match:
            match_list.append(match.group(0))
            text = text[match.end():]
        else:
            return match_list

此外,请注意,您的between_brackets正则表达式不能处理嵌套的括号:
re.findall('\(.*?\)', "(ac(ssc)xxz)")
>>> ['(ac(ssc)']

谢谢。也许更优雅的做法是将匹配语句作为 while 循环条件,并将返回语句放在循环外部。 - Marc Wagner
啊,别管了。你不能将赋值作为 while 语句的一部分。 - Marc Wagner
谢谢您指出这一点。我知道在我尝试解析的数据中不会出现这些情况。如果确实有这种情况,我应该如何处理? - Marc Wagner
1
正则表达式不是处理递归文本的正确工具。如果需要处理递归文本,可以实现此处接受的答案中描述的解决方案(https://dev59.com/rXRB5IYBdhLWcg3wv5tA#524624)。 - manic.coder
谢谢你提供的链接。对于我的情况,正则表达式是否合适,还是你建议在这里使用子程序? - Marc Wagner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接