Ira*_*ues 1 regex awk grep sed c-preprocessor
我有一堆C文件,我需要计算有多少#ifdef子句具有#elif子句,但在那些文件中没有#else子句,包括可能嵌套的#ifdef子句。例如,在第一个代码段中没有匹配项,而在第二个代码段中有两个匹配项:
#ifdef A
...
#elif B
...
#else
...
#endif
Run Code Online (Sandbox Code Playgroud)
#ifdef X1
...
#elif X2
...
#endif
...
#ifdef Y1
...
#elif Y2
...
#elif Y3
...
#endif
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种使用某些命令行工具(例如grep,awk或sed)执行此操作的方法,但到目前为止还没有运气。因此,我仍然愿意寻求更简便的选择(如果有)。
我已经使用grep尝试过此正则表达式:('^(?=.*#elif)((?!#elif|#else).)(?=.*\#endif).)*$'一个#elif后面没有另一个#elif或#else并具有一个对应的#endif),但是它不起作用,因为子句位于不同的行。
您需要编写一个递归下降解析器,该解析器在每次找到“ #ifdef”时下降,并在每次找到“ #endif”时返回。请参见如何在UNIX中比较和替换不同行中的字符串用awk编写的示例,。
您没有提供有用的样本输入或预期输出,因此我必须自己进行测试(因此可能不一定正是您所需要的),但是您将需要以下内容:
$ cat tst.awk
function descend(cond, numElifs,numElses,gotEndif) {
while ( !gotEndif && (getline > 0) ) {
if ( /#ifdef/ ) { descend($2) }
else if ( /#elif/ ) { numElifs++ }
else if ( /#else/ ) { numElses++ }
else if ( /#endif/ ) { gotEndif++ }
}
print cond, numElses+0, numElifs+0, ((numElifs>0)&&(numElses==0) ? "UhOh" : "")
return
}
/#ifdef/ { descend($2) }
Run Code Online (Sandbox Code Playgroud)
。
$ cat file
#ifdef A
#elif B
#else
#ifdef C
#elif D
#endif
#ifdef E
#elif F
#else
#endif
#ifdef G
#elif H
#ifdef I
#else
#endif
#elif J
#endif
#endif
Run Code Online (Sandbox Code Playgroud)
。
$ awk -f tst.awk file
C 0 1 UhOh
E 1 1
I 1 0
G 0 2 UhOh
A 1 1
Run Code Online (Sandbox Code Playgroud)
请注意,这是对getline的适当使用,但在其他地方使用它之前,请参阅http://awk.info/?tip/getline。
所有关于确实需要语言解析器(例如处理注释或字符串中的#ifdef)而不是像这样的脚本的常见警告。