Overlapping matches with finditer() in Python

余生颓废 提交于 2019-12-02 00:18:20

A character consumed is consumed, you should not ask the regex engine to go back.

From your examples the verse part (e.g. :1) seems not optional. Removing that will match the last bit.

ref_regex = re.compile('''
(?<!\w)                      # Not preceeded by any words
((?i)q(?:uote)?\s+)?            # Match 'q' or 'quote' followed by many spaces
(
    (?:(?:[1-3]|I{1,3})\s*)?    # Match an arabic or roman number between 1 and 3.
    [A-Za-z]+                   # Match many alphabetics
)\.?                            # Followed by an optional dot
(?:
    \s*(\d+)                    # Match the chapter number
    (?:
        [:.](\d+)               # Match the verse number
        (?:-(\d+))?             # Match the ending verse number
    )                    # <-- no '?' here
)
(?:
    \s+
    (?:
        (?i)(?:from\s+)|        # Match the keyword 'from' or 'in'
        (?:in\s+)|
        (?P<lbrace>\()      # or stuff between (...)
    )\s*(\w+)
    (?(lbrace)\))
)?
''', re.X | re.U)

(If you're going to write a gigantic RegEx like this, please use the /x flag.)


If you really need overlapping matches, you could use a lookahead. A simple example is

>>> rx = re.compile('(.)(?=(.))')
>>> x = rx.finditer("abcdefgh")
>>> [y.groups() for y in x]
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('e', 'f'), ('f', 'g'), ('g', 'h')]

You may extend this idea to your RegEx.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!