2009-05-16 5 views
0

아래 스크립트는 텍스트 파일에서 함수 이름을 사용하고 여러 c, h 파일이 들어있는 폴더에서 검사합니다. 이 파일을 하나씩 열고 은 각 행을 읽습니다. 파일의 일부에서 일치하는 항목이 발견되면 줄 번호와 일치 항목이 포함 된 줄을 인쇄합니다.Perl의 다른 파일에서 한 파일의 문자열을 어떻게 찾을 수 있습니까?

비교가 제대로 작동하지 않는 것을 제외하면 모든 것이 잘 작동합니다. 나는 누구든지 내 문제를 해결해 주신 것에 매우 감사 할 것입니다.

#program starts: 

    use FileHandle; 
    print "ENTER THE PATH OF THE FILE THAT CONTAINS THE FUNCTIONS THAT YOU WANT TO  
    SEARCH: ";#getting the input file 
    our $input_path = <STDIN>; 
    $input_path =~ s/\s+$//; 
    open(FILE_R1,'<',"$input_path") || die "File open failed!"; 
    print "ENTER THE PATH OF THE FUNCTION MODEL: ";#getting the folder path that 
               #contains multiple .c,.h files 
    our $model_path = <STDIN>; 
    $model_path =~ s/\s+$//; 
    our $last_dir = uc(substr ($model_path,rindex($model_path, "\\") +1)); 
    our $output = $last_dir."_FUNC_file_names"; 

    while(our $func_name_input = <FILE_R1>)#$func_name_input is the function name 
              #that is taken as the input 
    { 
    $func_name_input=reverse($func_name_input); 
    $func_name_input=substr($func_name_input,rindex($func_name_input,"\("+1); 
    $func_name_input=reverse($func_name_input); 
    $func_name_input=substr($func_name_input,index($func_name_input," ")+1); 

    #above 4 lines are func_name_input is choped and only part of the function 
    #name is taken. 

    opendir FUNC_MODEL,$model_path; 
    while (our $file = readdir(FUNC_MODEL)) 
    { 
     next if($file !~ m/\.(c|h)/i); 
     find_func($file);  
    } 
    close(FUNC_MODEL); 
    } 


    sub find_func() 
    { 
    my $fh1 = FileHandle->new("$model_path//$file") or die "ERROR: $!"; 

    while (!$fh1->eof()) 
    { 
     my $func_name = $fh1->getline(); #getting the line 

     **if($func_name =~$func_name_input)**#problem here it does not take the 
               #match 
     { 
      next if($func_name=~m/^\s+/); 
      print "$.,$func_name\n"; 
     } 
     } 
    } 
+1

$ func_name_input에 수행하는 reverse/substr/rindex 물건은 무엇입니까? – Schwern

답변

2
$func_name_input=substr($func_name_input,rindex($func_name_input,"\("+1); 

당신은 종료 괄호를 놓치고있어. 다음과 같아야합니다 :

$func_name_input=substr($func_name_input,rindex($func_name_input,"\(")+1); 

아마도 네 문장보다 쉬운 방법 일 것입니다. 그러나 내 머리를 감싸는 것은 조금 일찍 끝납니다. "function foo() {"에서 "foo"를 일치시겠습니까? 그렇다면/\ s + ([^)] +) /와 같은 정규식을 사용할 수 있습니다.


당신이 $func_name =~$func_name_input

, 당신은 특수 정규식 문자로 $의 func_name_input의 모든 문자를 치료하고 있습니다. 이것이 의도하지 않는 것이라면 quotemeta (perldoc -f quotemeta) : $func_name =~quotemeta($func_name_input) 또는 $func_name =~ qr/\Q$func_name_input\E/을 사용할 수 있습니다.


디버깅 strictures (그리고 구문 hilighting 편집기)와 쉬울 것입니다. 또한 다른 파일에서 이러한 변수를 사용하지 않는다면 "우리"는 파일 범위 변수에 대해 "내"가하지 않는 것을 수행하지 않습니다.

1

find + xargs + grep은 원하는 것의 90 %를 차지합니다.

find . -name '*.[c|h]' | xargs grep -n your_pattern 

ack 그것을 더 쉽게한다.

ack --type=cc your_pattern 

단순히 함께 귀하의 파일 "또는"그들로부터 패턴의 목록을.

이렇게하면 검색중인 패턴마다 한 번만 검색하면되는 이점이 있습니다.

1

나는 여전히 당신이 단지 ack를 사용해야한다고 생각하지만, 당신의 코드는 심각한 사랑이 필요했다.

다음은 개선 된 프로그램 버전입니다. 이제 파일을 요청 (및 사용자 쓰기) 할 필요없이 디렉토리를 검색하고 명령 행에서 패턴을 지정합니다. File :: Find를 사용하여 디렉토리 아래의 모든 파일을 검색합니다. 모든 패턴을 정규 표현식으로 연결하여 한 번에이 작업을 수행합니다. index()와 substr(), reverse() 대신에 regexes를 사용합니다. FileHandle 모듈보다는 파일 핸들을 내장하고 eof()를 확인하기 만하면됩니다. 모든 것은 글로벌 (우리) 대신 어휘 (내)로 선언됩니다. 더 쉬운 디버깅을 위해 엄격한 경고와 경고가 켜져 있습니다.

#!/usr/bin/perl 

use strict; 
use warnings; 
use File::Find; 

die "Usage: search_directory function ...\n" unless @ARGV >= 2; 

my $Search_Dir = shift; 
my $Pattern = build_pattern(@ARGV); 

find(
    { 
     wanted => sub { 
      return unless $File::Find::name =~ m/\.(c|h)$/i; 
      find_func($File::Find::name, $pattern); 
     }, 
     no_chdir => 1, 
    }, 
    $Search_Dir 
); 


# Join all the function names into one pattern 
sub build_pattern { 
    my @patterns; 
    for my $name (@_) { 
     # Turn foo() into foo. This replaces all that reverse() and rindex() 
     # and substr() stuff. 
     $name =~ s{\(.*}{}; 

     # Use \Q to protect against regex metacharacters in the input 
     push @patterns, qr{\Q$name\E}; 
    } 

    # Join them up into one pattern. 
    return join "|", @patterns; 
} 


sub find_func { 
    my($file, $pattern) = @_; 

    open(my $fh, "<", $file) or die "Can't open $file: $!"; 

    while (my $line = <$fh>) { 
     # XXX not all functions are unindented, but your choice 
     next if $line =~ m/^\s+/; 

     print "$file:$.: $line" if $line =~ $pattern; 
    } 
} 
+0

안녕하세요, 귀하의 응답을 주셔서 감사합니다 ....하지만 초보자가 펄 .. uplain 날 자세히 자세하게 할 수 ... 내가 ur 코드를 실행하면 오류가 발생 ... 감사합니다 다시 많이 ...내 의도는 텍스트 파일에 함수 이름 목록이 있고 폴더에 들어있는 모든 C 파일과 H 파일에서 해당 함수 이름을 검색하여 줄 번호와 전체 줄을 표시하고 싶다는 것입니다. 예를 들면 ... 텍스트 파일에서 foo() 나 void foo (abc) 나 foo만을 사용할 수도 있습니다 ... 그래서 foo를 혼자서 사용하고 사용법을 검색해야합니다. 전화 ... 내 prob를 해결하면 고마워. – User1611

+0

좋은 깨끗한 코드,하지만 당신은 오류가있어. File :: Find는 작업 디렉토리를 변경합니다. find_func (15 번째 줄)에 대한 호출을 다음과 같이 수정하면 : findunc ($ _, $ Pattern); 코드가 작동합니다. – daotoad

+0

@daotoad 아, 내게 항상 도움이 되었기 때문에 나를 위해 일했습니다. $ _을 사용하면 일치하는 파일의 전체 경로를 인쇄 할 수 없기 때문에 완전히 올바르지 않습니다. 대신 no_chdir과 $ File :: Find :: name을 사용할 것이다. 감사. – Schwern

관련 문제