如何在C源代码中搜索简单的if语句?
我想在C源文件集合中搜索简单的如何在C源代码中搜索简单的if语句?,c,regex,search,awk,C,Regex,Search,Awk,我想在C源文件集合中搜索简单的if语句 以下是以下形式的声明: if (condition) statement; if (condition) { statement; statement; } 任何数量的空白或其他序列(例如“}else”)都可能出现在if前面的同一行中。注释可能出现在“如果(条件)”和“声明;”之间 我想排除以下形式的复合语句: if (condition) statement; if (condition) { stateme
if
语句
以下是以下形式的声明:
if (condition)
statement;
if (condition)
{
statement;
statement;
}
任何数量的空白或其他序列(例如“}else”)都可能出现在if
前面的同一行中。注释可能出现在“如果(条件)”和“声明;”之间
我想排除以下形式的复合语句:
if (condition)
statement;
if (condition)
{
statement;
statement;
}
我在awk中尝试了以下各项:
awk '/if \(.*\)[^{]+;/ {print NR $0}' file.c # (A) No results
awk '/if \(.*\)[^{]+/ {print NR $0}' file.c # (B)
awk '/if \(.*\)/ {print NR $0}' file.c # (C)
(B) 和(C)给出不同的结果。两者都包括我要查找的项目和我要排除的项目。显然,问题的一部分在于如何处理跨越多条线的模式
可以忽略边缘情况(格式错误的注释、奇数缩进或奇数位置的大括号等)
如何实现这一点?我不确定如何使用一行程序来实现这一点(我确定可以使用sed的'n'命令来读取下一行,但这将非常复杂),因此您可能需要使用脚本来实现这一点。那么:
perl parse_if.pl file.c
其中parse_if.pl包含:
#!/usr/bin/perl -w
my $line_number = 0;
my $in_if = 0;
my $if_line = "";
# Scan through each line
while(<>)
{
# Count the line number
$line_number += 1;
# If we're in an if block
if ($in_if)
{
# Check for open braces (and ignore the rest of the if block
# if there is one).
if (/{/)
{
$in_if = 0;
}
# Check for semi-colons and report if present
elsif (/;/)
{
print $if_line_number . ": " . $if_line;
$in_if = 0;
}
}
# If we're not in an if block, look for one and catch the end of the line
elsif (/^[^#]*\b(?:if|else|while) \(.*\)(.*)/)
{
# Store the line contents
$if_line = $_;
$if_line_number = $line_number;
# If the end of the line has a semicolon, report it
if ($1 =~ ';')
{
print $if_line_number . ": " . $if_line;
}
# If the end of the line contains the opening brace, ignore this if
elsif ($1 =~ '{')
{
}
# Otherwise, read the following lines as they come in
else
{
$in_if = 1;
}
}
}
#/usr/bin/perl-w
我的$line_编号=0;
如果=0,我的$in_;
我的$if_line=“”;
#浏览每一行
while()
{
#数一数行号
$line_number+=1;
#如果我们在If区
如果($in_-if)
{
#检查是否有打开的大括号(忽略if块的其余部分
#如果有的话)。
if(/{/)
{
$in_,如果=0;
}
#检查分号,并报告是否存在分号
elsif(/;/)
{
打印$if_行编号。“:”$if_行;
$in_,如果=0;
}
}
#如果我们不在If区,寻找一个,然后抓住线的末端
elsif(/^[^#]*\b(?:if | else | while)\(.*)(.*)/)
{
#存储行内容
$if\u line=$\u;
$if_line_number=$line_number;
#如果行尾有分号,请报告它
如果($1=~';'))
{
打印$if_行编号。“:”$if_行;
}
#如果线的末端包含开口大括号,则忽略此项(如果有)
elsif($1=~'{')
{
}
#否则,请在输入时阅读以下行
其他的
{
$in_,如果=1;
}
}
}
如果您愿意,我相信您可以用任何其他语言(包括awk)非常轻松地完成某些操作;我只是想通过一个例子,用perl可以最快地完成这些操作。在awk中,每一行都被视为一条记录,并且“\n”是记录分隔符。因为所有记录都是逐行解析的,所以您需要在if之后跟踪下一行。我不知道如何在awk中做到这一点。。 在perl中,您可以像 open(INFO,"<file.c"); $flag=0; while($line = <INFO>) { if($line =~ m/if\s*\(/ ) { print $line; $flag = 1; } else { print $line && $flag ; $flag = 0 if($flag); } }
使用Awk打开(信息,“您可以通过以下方式完成此操作:
awk '
BEGIN { flag=0 }
{
if($0 ~ /if/) {
print $0;
flag=NR+1
}
if(flag==NR)
print $0
}' try.c
基于Al的回答,但修复了几个问题(另外我还决定检查simple
else
子句(同时,它还打印完整的if块):
!/usr/bin/perl-w
我的$line_编号=0;
如果=0,我的$in_;
我的$if_line=“”;
#ifdef新
我的$block=“”;
#endif/*新*/
#浏览每一行
while()
{
#数一数行号
$line_number+=1;
#如果我们在If区
如果($in_-if)
{
$block=$block.$line_编号“+”$\u;
#检查是否有打开的大括号(忽略if块的其余部分
#如果有的话)。
if(/{/)
{
$in_,如果=0;
$block=“”;
}
#检查分号,并报告是否存在分号
elsif(/;/)
{
打印$if_行;
打印$block;
$block=“”;
$in_,如果=0;
}
}
#如果我们不在If区,寻找一个,然后抓住线的末端
elsif(/(如果\(.*\)[^#]其他)(.*/)
{
#存储行内容
$if_line=$line_number.“:”$;
#如果行尾有分号,请报告它
如果($2=~';'))
{
打印$if_行;
}
#如果线的末端包含开口大括号,则忽略此项(如果有)
elsif($2=~'{')
{
}
#否则,请在输入时阅读以下行
其他的
{
$in_,如果=1;
}
}
}
Oops,如果我没记错的话,(B)应该没有分号。我将编辑这个问题以反映这一点。我发布了一个基于你的修改版本。它修复了几个问题。一:你的重复查找行,因为成功查找分号不会终止块(在第一个“elsif”中没有“$in_if=0;”).2:Yours用分号打印带有“if”的行的行号(使“$if\u line=$line\u number.”:“$\u;”并从打印语句中删除它来修复它)。很好的一点,谢谢(我想我只是很快地完成了我的代码,没有太多的顾虑)。我将修改我的源代码以处理这些注释。我故意想打印包含if开头的行,因此我认为它还应该打印if的行号…我还更改了if行的检查以查找else/while,并验证关键字前没有任何“#”字符。这不是理想的方法要做到这一点(一种更健壮的方法是在if/else之前检查(#\s*),但我有点懒。这会导致的唯一明显问题是在这样一行上:/*用#*/if(某物)注释)。显然,有很多方法可以改进它来完成任何你需要它做的事情!是的,注释中的分号也会把它扔掉。这不一定有帮助,但另一个答案是:如果你可以访问支持MISRA-C指南的Lint类型工具,这将为你提供所有类型的if()语句,因为不带括号的if()语句违反了准则。在我看来,这是一个一行程序处理起来太麻烦的问题。