在Python中使用正则表达式反向搜索字符串?
背景
我正在解析一些代码,想要找到函数前面的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 个回答
我觉得你应该使用一个正则表达式,只匹配在函数前面的文档注释。可以用这样的方式(简单的例子):
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*\()"
就可以了。
最简单的方法就是直接使用一个组,你不需要往回找...
(commentRegex)functionRegex
然后只需提取组1。你需要在多行模式下运行才能让它工作,我不太懂Python,所以帮不了你更多。
用前瞻断言也可以做到,但这个方法更简单。
这可以通过一个简单的正则表达式来实现。
关键是要捕捉到你想要的函数前面的注释。最简单的方法是使用非贪婪的匹配方式。比如说,你可以用这个表达式:/\*\*(.*?)\*/
,并加上多行模式;不过在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 = "(/\*\*(?:[^\*]|\*(?!/))*\*/)"
。
希望这对你有帮助。