2009-07-03 59 views
3

我想在C源文件集合中搜索簡單的if語句。如何在C源代碼中搜索簡單的if語句?

這些形式的語句:

if (condition) 
    statement; 

可能出現在if之前在同一行的空格或其他序列(例如,「}其他」)的任何量。評論可能出現在「if(條件)」和「聲明」之間。

我要排除的形式的複合語句:

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

(A)和(B)是相同的 – DrAl 2009-07-03 10:56:26

+0

哎呀,如果我r (B)應該沒有分號。我將編輯該問題以反映這一點。 – 2009-07-03 13:13:39

回答

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中做到最快。

+0

我發佈了一個基於你的修改版本。它修復了一些問題。一:你重複發現的行,因爲成功找到一個分號不會終止塊(第一個「elsif」中沒有「$ in_if = 0;」)。二:你用「if」(製作「$ if_line = $ line_number。」:「。$ _;」並從打印語句中刪除它修復該行)打印行號的分號。 – 2009-07-03 13:30:36

+0

好點,謝謝你(我只是非常快速地打開了我的代碼,不用太在意,我猜)。我會修改我的來源來處理這些評論。我故意要打印包含的,如果一開始就行,所以我想這也應該打印的,如果... – DrAl 2009-07-03 13:33:15

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); 
} 
} 
0

用awk你可以這樣做:

awk ' 
BEGIN { flag=0 } 
{ 
    if($0 ~ /if/) { 
     print $0; 
     flag=NR+1 
    } 
    if(flag==NR) 
     print $0 
}' try.c 
2

基於鋁的答案,但一對夫婦的問題的修補程序(加上我決定檢查簡單else條款,太(也,它打印完整如果塊):

#!/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; 
     } 
    } 
}