背景
当前在工程中有已经实现好了的很多c函数,由于某些原因,需要在所有c函数中临时加些一样的语句,这些语句最后会删除
解决方案1
参考: https://codeantenna.com/a/Rh6TZnp9Km
经过一番研究和搜索,得出以下的一个正则表达式(注意调用的时候忽略换行符),
该表达式可以查找几乎所有形式的函数(函数返回值是自定义的结构体的除外),他的优点是可以定位函数的任一部位(函数返回值,函数名,第一个参数,等),缺点是在正常的代码环境中,由于匹配项太多,速度非常慢.很不实用
表达式
# 匹配字符串
rgl_func_def = r'''
(\s*) #匹配所有的空白字符
(
(const)?(volatile)?(static)?\s*(inline)?\s*(extern)?\s*
(
(VOID)|(void)|(enum)|
((unsigned)?(signed)?(long)?\s*(int)|(char)|(float)|(short)|(long)|(double))|
(bool)|(struct\s*\w+)|(union\s*\w+)|(wait_queue_t)|(wait_queue_head_t)|(\w+)
)
\s*(fastcall)?
) #匹配函数返回类型
(\s*(\*)?\s*) #识别有无指针类型*,以及空白字符
(\w+) #识别函数名称
((\s*)(\()(\n)?) #识别函数开始小括号
((\s*)?(const)?(volatile)?(\s*)? #参数前是否有const、volatile
(
(static)?\s*(inline)?\s*(extern)?\s*
(
(VOID)|(void)|(enum)|
((unsigned)?(signed)?(long)?\s*\s*(int)|(char)|(float)|(short)|(long)|(double))|
(bool)|(struct\s*\w+)|(union\s*\w+)|(wait_queue_t)|(wait_queue_head_t)|(\w+)
)
\s*(fastcall)?
) #参数类型
(\s*)(\*)?(\s*)?(restrict)?(\s*)?(\w+)(\s*)?(\[(\d|\s)*?\])?(\s*)?(\,)?(\n)?(.*)?)*
((\s*)(\))(\n)?) #函数结束小括号
'''
解决方案2
按照c函数的特点,函数的结构一定是如下:
返回类型(至少是一个词),指针(可能有),函数名,(,参数,)
而且参数中,包括的符号类型不多,因此得出以下正则表达式
rgl = r'\w+(\s|\n|\*)+\w+(\s|\n)*\((\s|\n|!|%|&|\(|\)|\*|\+|,|-|\/|\w|\[|\\|\]|\^|\||~|<{2}|>{2})*?\)(\n|\s)*\{'
解释
这里最主要的就是用 (\s|\n|!|%|&|(|)|*|+|,|-|/|\w|[|\|]|^|||~|<{2}|>{2} 来表示函数的参数部分,常规来说,该表达式能匹配到所有的函数定义,但由于有的写法合法但是不常规,所以有可能会导致匹配到的不是函数定义(只是有可能,我暂时还没遇到)
所以这里给出了一个防范于未然的措施
1.对于 (\s|\n|!|%|&|(|)|*|+|,|-|/|\w|[|\|]|^|||~|<{2}|>{2} , 这里给出了几个常见的合法组合但一定不会出现在函数定义的表达式
rgl_exclude_list = [r'&&', r'\|\|', '->']
可以在匹配到的结果里检查上面几个表达式,如果有,那就不是函数定义
2.最好把c语言的注释先过滤掉,在注释里会写很多非法语句,很有可能会被匹配到.
结论
以上就是我的方案,我使用了方案2解决了问题,并且没有匹配到额外的情况(我也是把注释语句过滤掉之后再匹配的)