【问题标题】:How to create multiline python regex to parse go imports如何创建多行 python 正则表达式来解析 go 导入
【发布时间】:2016-09-01 23:19:14
【问题描述】:

我正在尝试使用 python 正则表达式解析以下内容。

import (
    "github.com/user/qrt"

    "fmt"

    "github.com/user/zyx"
)

import "abcdef"

import "abzdef"

理想情况下,单个正则表达式会产生:

括号内的所有内容作为一个组,单行导入语句中的每个项目作为一个组

这是我对每个导入语句分别拥有的内容。 (见冒号右边的位..

# import (...)  : r'import\s*(\()(.*?)(\))'
# import ".."   : r'import\s*(\")(.*?)(\")'

我想我可以使用类似下面的东西来匹配第一组来决定我是在解析 () 导入还是 "" 导入。 (?(id)yes|no) 如果组 'id' 匹配,则匹配 'yes',否则匹配 'no'

【问题讨论】:

    标签: python regex backreference


    【解决方案1】:

    这样的?

    Ideone.com

    import re
    
    test = """import (
        "github.com/user/qrt"
    
        "fmt"
    
        "github.com/user/zyx"
    )
    
    import "abcdef"
    
    import "abzdef"
    """
    
    rx = re.compile(r'import\s+([^(]+?$|\([^)]+\))', re.MULTILINE)
    rx2 = re.compile(r'".*"', re.MULTILINE)
    
    for m in rx.finditer(test):
        imp = m.group(1)
        if imp[0] == '(':
            for m in rx2.finditer(imp):
                print(m.group(0))
        else:
            print(m.group(1))
    

    输出

    "github.com/user/qrt"
    "fmt"
    "github.com/user/zyx"
    "abcdef"
    "abzdef"
    

    编辑 只是为了好玩,我尝试了一个模型递归下降解析器。它允许破坏语法;但这是一个想法,而且易于使用,只需迭代即可。

    http://ideone.com/iS4aww

    import re
    
    test = """import (
        "github.com/user/qrt"
    
        "fmt"
    
        "github.com/user/zyx"
    )
    
    import "abcdef"
    
    import "abzdef"
    """
    
    BEGIN = 1
    IMPORT = 2
    DESCENT = 3
    
    
    class Lexer(object):
        def __init__(self, text):
            self._rx = re.compile(r'(import|".*?"|\(|\))')
            self._text = text
    
        def __iter__(self):
            for m in self._rx.finditer(self._text):
                yield m.group(1)
    
    
    class RecursiveDescent(object):
        state = BEGIN
    
        def __init__(self, lexer):
            self._lexer = lexer
    
        def __iter__(self):
            for token in self._lexer:
                if self.state == BEGIN:
                    if token != 'import':
                        # Beginning of the program most likely
                        raise StopIteration
                    self.state = IMPORT
                elif self.state == IMPORT:
                    if token == '(':
                        self.state = DESCENT
                    else:
                        self.state = BEGIN
                        yield token
                elif self.state == DESCENT:
                    if token == ')':
                        self.state = BEGIN
                    else:
                        yield token
    
    for path in RecursiveDescent(Lexer(test)):
        print(path)
    

    输出

    "github.com/user/qrt"
    "fmt"
    "github.com/user/zyx"
    "abcdef"
    "abzdef"
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多