模块级常量的Python正则表达式

时间:2011-10-27 12:19:27

标签: python regex full-text-search

我已经回过头来寻找可能解决我问题的方法,但我想我今天的google-fu非常糟糕。更不用说我对正则表达式的了解,它接近于零。

我试图仅使用文本处理从一系列Python文件中检索一些“常量”(即模块级全局变量)的定义。基本上,我阅读了Python文件的全文,然后我将正则表达式应用于文本,以找出这些“常量”的位置/内容。

作为一个例子,我可以在我的Python文件中使用以下内容:

CONSTANT_ONE   = 0    # standard
CONSTANT_RIGHT = 1    # rotation of 90 on the right
CONSTANT_LEFT  = 2    # rotation of 90 on the left

我发现这个正则表达式可以提取变量名称

re.compile('^(\w+)[ \t]*=', re.M)

然而,这些声明严重失败:

NAME1, NAME2 = 0, None
CONST_1, CONST_2, CONST_3 = range(3)

有什么方法可以修改我的正则表达式以处理这两种情况?如果这是一个非常基本的问题我很抱歉,但我真的不是正则表达式的专家......

提前谢谢。

安德烈。

3 个答案:

答案 0 :(得分:3)

我认为使用正则表达式实现这一目标并不容易。可以compile Python模块,然后向下走AST来查找变量定义。请参阅http://docs.python.org/library/functions.html#compilehttp://docs.python.org/library/ast.html#module-ast上的文档。

编辑:我当前的程序,使用@Sven的想法。

#!/usr/bin/env python

import ast
import sys

# example assignment.
a, b=5, 9

class MyNodeVisitor(ast.NodeVisitor):
        """
        Visit nodes in AST. Idea from @Sven.
        """
        def visit_Name(self, node):
                if isinstance(node.ctx, ast.Store):
                        print "Assigning name '%s' on line %d" % ( \
                                node.id, node.lineno)
        def visit_FunctionDef(self, node):
                pass
        def visit_ClassDef(self, node):
                pass

def printAssignments(name):
        """
        Read Python file and print a list of variable assignments.
        """
        # read file.
        f=open(name, 'rU')
        data=f.readlines()
        f.close()

        # create AST.
        t=ast.parse("".join(data), filename=name, mode='exec')

        # find assignments.
        MyNodeVisitor().visit(t)

        # walk nodes.
        # for node in ast.walk(t):
        #       if isinstance(node, ast.Name) \
        #          and isinstance(node.ctx, ast.Store) \
        #          and node.col_offset == 0:
        #               print "Assigning name '%s' on line %d" % (node.id, node.lineno)

# print all assignments from files.
for name in sys.argv[1:]:
        print "=== %s ===" % name
        printAssignments(name)
        print "====%s====" % ('='*len(name), )

答案 1 :(得分:3)

不要使用正则表达式,而是使用Python的解析器。它更简单:

class TargetExtractor(ast.NodeVisitor):
    def visit_Name(self, node):
        if isinstance(node.ctx, ast.Store):
            print node.id
    def visit_FunctionDef(self, node):
        pass
    def visit_ClassDef(self, node):
        pass

TargetExtractor().visit(ast.parse("a, b = 2, 3; c = d"))

打印

a
b
c

您也可以将文件的全部内容传递给ast.parse()

,而不是字符串

答案 2 :(得分:0)

我不知道你这样做的目的是什么,但如果由于某些原因它必须是一个正则表达式(如果不是Svens的回答看起来相当不错+1),这里就是一个:

^([\w\s,]+)=

在此处查看online on Regexr

但这比你想要的更加通用和匹配。