2010-08-10 44 views
1

我想以檢索無功能(僅定義的函數,而不是調用函數)存在於一個文本文件(計數)發現很難解決通過檢查我編輯的代碼this.Please引導

的文本文件{} function.txt低於

#include<main.h> 
#include<mncl.h> 
int reg23; 
int refid23; 
int64 AccounntBalance(char *reg12,char *refid,char **id){ //dis is function1 
ref(); 
if(id>100) 
    { 
    do(&ref); 
    } 
}              //dis is end of fucntion1 
void AccountRetrivalForm(char **regid,char **balance,char **id) //dis is function2 
    { 
    doref(); 
    int register; 
    if(refid!=null) 
    { 
    dolog(); 
    } 
    }              //dis is end of function2 

現在程序按照我的邏輯是:

#!C:/strawberry/perl 
use strict; 
use warnings; 
my $filename = 'function_perl.txt'; 
my $function_count = 0; 
open(FILENAME,$filename); 
my @arr = join("\n",<FILENAME>); 
foreach my $string(@arr) 
    { 
if($string =~/(?:int64|void|boolean)\s?(.*?)\(.*?\)\s*\{/) 
    { 
print "HAI"; 
$function_count++; 
print '$function_count'; 
    } 
    } 

這裏Function_count是1.It從來沒有增量的第二場比賽....請幫助我用同一個鱈魚é...我想這麼久,我很難解決這個問題。

+0

究竟是你想搭配什麼?以(int64)或(void)或(boolean)開頭的函數? – GorillaPatch 2010-08-10 13:27:31

+0

@gorillaPatch 我嘗試匹配所有可能以int64開頭的函數或void或布爾值(這是唯一的三個可能性) – Sreeja 2010-08-10 13:29:59

+1

我很好奇,什麼語言是「dis」? – Ether 2010-08-10 15:07:18

回答

3

您的正則表達式格式不正確。

^([int64/void/boolean)]/(.*)/\(/\{//\n 

你可能意味着類似:

/^(int64|void|boolean)\s+(\w+)\s*\(.*?\)\s*\{/ 

也就是說,int64一個,void,或者boolean,一些空白,標識符,可選的空格,左括號,一些內容,一個右括號,一些可選的空白(可能是一個換行符)和一個開放的大括號。

3

我想說,你通過這個文件的方式是不尋常的。通常你會使用類似

open my $handle, '<', $filename; 
while (<$handle>) { 
    if (/^(void|boolean|int64).../) { 
     do something; 
    } 
} 
close $handle; 

代碼的作用是打開文件並一次讀入一行。這與通過獲取整個數組,加入並迭代其元素的方式相同。

使用Perl中的無關然而,重要提示:包括你的腳本開始後三條線:

#!/usr/bin/perl 
use strict; 
use warnings; 
use autodie qw(:all); 

此提醒您,如果有您嘗試在例如串聯使用一些未分配的變量和其他事情。嚴格的包迫使你用my關鍵字聲明變量。這聽起來有點麻煩,但它也可以防止你得到問題,因爲你錯誤地輸入了一個變量。嚴格使用Perl解釋器會警告你一個未聲明的變量。 autodie編譯指示檢查系統調用失敗,如open

您正在使用的正則表達式是錯誤的。你必須知道Perl中的正則表達式用斜線括起來,所以/\s+\w*.*/是一個有效的正則表達式。你在這裏使用正則表達式的斜槓,它會過早地關閉表達式。如果你必須在你的文本中重新匹配斜線,你將不得不使用反斜線或完全使用不同的分隔符。

順便說一句,你也有一個錯字:@filecontent@file_content。這是一個完美的地方,use strict;會警告你。

+0

@daxim感謝您的編輯。爲什麼使用$ handle形式的文件句柄而不是FILENAME更好? – GorillaPatch 2010-08-10 13:53:21

+1

http://stackoverflow.com/questions/1479741/why-is-three-argument-open-calls-with-lexical-filehandles-a-perl-best-practice – daxim 2010-08-10 16:20:18

+0

感謝您提供的建議daxim – Sreeja 2010-08-10 16:59:04

4

也許這個例子可以幫助:

use strict; 
use warnings; 

my $n; 

# Supply the input file name as a command-line argument. 
# Perl will open the file and process it line by line. 
# No need to hard-code the file name in the program, which 
# means the script could be reused. 
while (my $line = <>){ 
    # The regex is applied against $line. 
    # It will return the items captured by parentheses. 
    # The /x option causes Perl to ignore whitespace 
    # in our definition of the regex -- for readability. 
    my ($type, $func, $args) = $line =~ /^ 
     (int64|void|boolean) \s+ 
     (\w+)    \s* 
     \((.+?) \) 
    /x; 

    # Skip the line if our regex failed. 
    next unless defined $type; 

    # Keep track of N of functions, print output, whatever... 
    $n ++; 
    print $_, "\n" for '', $type, $func, $args; 
} 

print "\nN of functions = $n\n"; 
+1

不錯的一個!我喜歡它如何直接命名正則表達式的匹配。使代碼更具可讀性。我今天學到了東西。謝謝! +1。 – GorillaPatch 2010-08-10 13:49:05

1

這將這樣的伎倆:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use autodie qw(:all); 

my $function_count = 0; 
open my $input, '<', 'function.txt'; 
while (defined(my $line = <$input>)) { 
    chomp($line); 

    if (my ($func) = $line =~ /^(?:int64|void|boolean)\s?(.*?)\(/) { 
     print qq{Found function "$func"\n}; 
     $function_count++; 
    } 
} 
close $input; 
print "$function_count\n"; 

修訂答案考慮到函數調用:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use autodie qw(:all); 

my $document; 
{ 
    local $/ = undef; 
    open my $input, '<', 'function.txt'; 
    $document = <$input>; 
    chomp $document; 
    close $input; 
} 

my $function_count = 0; 
while (my ($func) = $document =~ /(?:int64|void|boolean)\s?(.*?)\(.*?\)\s*\{/gs)) { 
    print qq{Found function "$func"\n}; 
    $function_count++; 
} 

print "$function_count\n"; 
+0

不需要chomp我認爲這是因爲你不匹配行末。 – GorillaPatch 2010-08-10 13:50:46

+0

非常真實的,只是添加chomp作爲習慣的力量。 – Narthring 2010-08-10 14:45:30

+0

Thanks.But上面的代碼返回甚至函數調用的計數.. int64 AccounntBalance(char * reg12,char * refid,char ** id); – Sreeja 2010-08-10 17:43:22

3

正則表達式是不解析器。如果可以的話,最好使用解析器。

一個簡單的辦法是在解析器傾身ctags

#! /usr/bin/perl 

use warnings; 
use strict; 

sub usage { "Usage: $0 source-file\n" } 

die usage unless @ARGV == 1; 

open my $ctags, "-|", "ctags", "-f", "-", @ARGV 
    or die "$0: failed to start ctags\n"; 

while (<$ctags>) { 
    chomp; 
    my @fields = split /\t/; 
    next unless $fields[-1] eq "f"; 
    print $fields[0], "\n"; 
} 

採樣運行:

$ ./getfuncs prog.cc 
AccounntBalance 
AccountRetrivalForm

另一種方法涉及G ++的選項-fdump-translation-unit,導致它傾倒分析樹的表示,你可以像下面的例子那樣挖掘它。

我們開始與平常前面的問題:

#! /usr/bin/perl 

use warnings; 
use strict; 

處理需要的源文件和任何必需的編譯標記的名稱。

sub usage { "Usage: $0 source-file [ cflags ]\n" } 

翻譯單元轉儲具有簡單的格式:

@1  namespace_decl name: @2  srcp: :0  
         dcls: @3  
@2  identifier_node strg: ::  lngt: 2  
@3  function_decl name: @4  mngl: @5  type: @6  
         srcp: prog.c:12    chan: @7  
         args: @8  link: extern 
@4  identifier_node strg: AccountRetrivalForm  lngt: 19 

正如你可以看到,每一個記錄開始的標識符,後跟一個類型,然後一個或多個屬性。正則表達式和一些哈希轉換足以給我們一棵樹來檢查。

sub read_tu { 
    my($path) = @_; 
    my %node; 

    open my $fh, "<", $path or die "$0: open $path: $!"; 
    my $tu = do { local $/; <$fh> }; 

    my $attrname = qr/\b\w+(?=:)/; 
    my $attr = 
    qr/($attrname): \s+ (.+?)  # name-value 
     (?= \s+ $attrname | \s*$) # terminated by whitespace or EOL 
     /xm; 

    my $fullnode = 
    qr/^(@\d+) \s+ (\S+) \s+ # id and type 
     ((?: $attr \s*)+)  # one or more attributes 
     \s*$     # consume entire line 
     /xm; 

    while ($tu =~ /$fullnode/g) { 
    my($id,$type,$attrs) = ($1,$2,$3); 

    $node{$id} = { TYPE => $type }; 
    while ($attrs =~ /$attr \s*/gx) { 
     if (exists $node{$id}{$1}) { 
     $node{$id}{$1} = [ $node{$id}{$1} ] unless ref $node{$id}{$1}; 
     push @{ $node{$id}{$1} } => $2; 
     } 
     else { 
     $node{$id}{$1} = $2; 
     } 
    } 
    } 

    wantarray ? %node : \%node; 
} 

在主程序中,我們喂代碼至g ++

die usage unless @ARGV >= 1; 

my($src,@cflags) = @ARGV; 
system("g++", "-c", "-fdump-translation-unit", @cflags, $src) == 0 
    or die "$0: g++ failed\n"; 

my @tu = glob "$src.*.tu"; 
unless (@tu == 1) { 
    die "$0: expected one $src.*.tu file, but found", 
     @tu ? ("\n", map(" - $_\n", @tu)) 
      : " none\n"; 
} 

假設一切順利,那麼我們挖出指定的源文件中給出的函數定義。

my $node = read_tu @tu; 

sub isfunc { 
    my($n) = @_; 
    $n->{TYPE} eq "function_decl" 
      && 
    index($n->{srcp}, "$src:") == 0; 
} 

sub nameof { 
    my($n) = @_; 
    return "<undefined>" unless exists $n->{name}; 
    $n->{name} =~ /^@/ 
    ? $node->{ $n->{name} }{strg} 
    : $n->{name}; 
} 

print "$_\n" for sort 
       map nameof($_), 
       grep isfunc($_), 
       values %$node; 

運行示例:

$ ./getfuncs prog.cc -I. 
AccounntBalance 
AccountRetrivalForm
+0

就是這樣做的。不過,我認爲你應該把ctags的方式放在前面。 – Svante 2010-08-10 16:31:32

+0

@Svante好的建議!更新。 – 2010-08-10 16:56:40

+0

我同意你的意見。這顯然是他想要處理的一個基於c語言的語言......而且用一些完全有效的函數聲明來打破任何正則表達式太容易了。最好使用理解語言的工具。 – 2010-08-11 18:27:59