在Python中使用正则表达式反向搜索字符串?

1 投票
7 回答
4787 浏览
提问于 2025-04-15 20:37

背景
我正在解析一些代码,想要找到函数前面的doxygen注释。不过,因为我想匹配特定的函数名,所以仅仅获取紧挨着的注释让我遇到了一些麻烦。

目前的方法

import re  
function_re = re.compile(
    r"\/\*\*(.+)\*\/\s*void\s+(\w+)\s*::\s*function_name\s*\(\s*\)\s*")  
function_match = function_re.search(file_string)
if function_match:  
    function_doc_str = update_match.group(2)

目前方法的问题
现在的方法会匹配到之前函数的doxygen注释,导致我得到的结果是错误的注释。

问题
有没有办法使用Python的正则表达式库向后搜索字符串?
看起来我的问题在于,比较严格的部分(出现频率较低的部分)是函数的签名,比如“void function()”。

可能更好的问题
有没有我忽略的更好(更简单)的方法?

7 个回答

2

我觉得你应该使用一个正则表达式,只匹配在函数前面的文档注释。可以用这样的方式(简单的例子):

import re

test = """

/**
    @doxygen comment
*/
void function()
{
}

"""

doxygenRegex = r"(?P<comment>/\*\*(?:[^/]|/(?!\*\*))*\*/)"
functionRegex = r"(?P<function>\s\w+\s+(?P<functionName>\w+)\s*\()"

match = re.search(doxygenRegex + functionRegex, test)
print match.groupdict()

只要这个正则表达式能匹配到东西,你就可以循环进行匹配——但下次要从test[match.end():]开始搜索。希望这样说你能理解……

顺便说一下,如果你只想提取注释,而不想要函数的内容,可以使用前瞻匹配——只需把functionRegex替换成r"(?=\s\w+\s+\w+\s*\()"就可以了。

2

最简单的方法就是直接使用一个组,你不需要往回找...

 (commentRegex)functionRegex

然后只需提取组1。你需要在多行模式下运行才能让它工作,我不太懂Python,所以帮不了你更多。

用前瞻断言也可以做到,但这个方法更简单。

2

这可以通过一个简单的正则表达式来实现。

关键是要捕捉到你想要的函数前面的注释。最简单的方法是使用非贪婪的匹配方式。比如说,你可以用这个表达式:/\*\*(.*?)\*/,并加上多行模式;不过在Python中,非贪婪模式和多行模式似乎不能一起使用(至少在我的环境里是这样)。所以,你需要用一个小技巧,如下:

/\*\*((?:[^\*]|\*(?!/))*)\*/

这个表达式的作用是匹配:

1: 注释的开始部分 /**

2: 任何不是 * 的字符,或者是 * 但后面不跟 / 的情况。

3: 注释的结束部分 */

根据这个思路,你需要的代码是:

function_name  = "function2"
regex_comment  = "/\*\*((?:[^\*]|\*(?!/))*)\*/"
regex_static   = "(?:(\w+)\s*::\s*)?"
regex_function = "(\w+)\s+"+regex_static+"(?:"+function_name+")\s*\([^\)]*\)"
regex = re.compile(regex_comment+"\s*"+regex_function, re.MULTILINE)
text  = """
/**
    @doxygen comment1
*/
void test::function1()
{
}

/**
    @doxygen comment2
*/
void test::function2()
{
}
"""
match = regex.search(text)
if (match == None): print "None"
else:               print match.group(1)

运行后,你会得到:


    @doxygen comment2

变体:如果你想同时捕捉到 /***/,可以使用 regex_comment = "(/\*\*(?:[^\*]|\*(?!/))*\*/)"

希望这对你有帮助。

撰写回答