我想在C源文件集合中搜索简单的if
语句。
这些是以下形式的陈述:
if (condition)
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)给出不同的结果。两者都包括我正在寻找的项目和我想要排除的项目。显然,部分问题在于如何处理跨越多行的模式。
边缘情况(错误形成的注释,奇数位置的奇数缩进或花括号等)可以忽略。
我该如何做到这一点?
答案 0 :(得分:2)
基于Al的答案,但修复了几个问题(另外我决定检查简单的else
子句(同样,它打印完整的if块):
#!/usr/bin/perl -w
my $line_number = 0;
my $in_if = 0;
my $if_line = "";
#ifdef NEW
my $block = "";
#endif /* NEW */
# Scan through each line
while(<>)
{
# Count the line number
$line_number += 1;
# If we're in an if block
if ($in_if)
{
$block = $block . $line_number . "+ " . $_;
# Check for open braces (and ignore the rest of the if block
# if there is one).
if (/{/)
{
$in_if = 0;
$block = "";
}
# Check for semi-colons and report if present
elsif (/;/)
{
print $if_line;
print $block;
$block = "";
$in_if = 0;
}
}
# If we're not in an if block, look for one and catch the end of the line
elsif (/(if \(.*\)|[^#]else)(.*)/)
{
# Store the line contents
$if_line = $line_number . ": " . $_;
# If the end of the line has a semicolon, report it
if ($2 =~ ';')
{
print $if_line;
}
# If the end of the line contains the opening brace, ignore this if
elsif ($2 =~ '{')
{
}
# Otherwise, read the following lines as they come in
else
{
$in_if = 1;
}
}
}
答案 1 :(得分:1)
我不确定你是如何使用一个衬垫(我确信你可以使用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;
}
}
}
如果你愿意的话,我相信你可以用任何其他语言(包括awk)轻松地做一些事情。我只是认为我可以通过一个例子在perl中最快地完成。
答案 2 :(得分:0)
在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); } }
答案 3 :(得分:0)
使用Awk,您可以通过以下方式执行此操作:
awk '
BEGIN { flag=0 }
{
if($0 ~ /if/) {
print $0;
flag=NR+1
}
if(flag==NR)
print $0
}' try.c