2009-05-06 36 views
5

を含むcppファイル内の関数を見つける方法は、本文に特定の単語を含む大きなcppファイル内の関数を探したいと思います。grep、vimのgrep、または他のunixシェルコマンドを使用して特定の単語

私が探している単語がインデントされた行にあります。対応する関数ヘッダーは、インデントされた行の上の最初の行で、位置0から始まり、 '{' 。次のコードスニペットにJOHN_DOE探したとえば

int foo (int arg1) 
{ 
    /// code 
} 
void bar (std::string arg2 ) 
{ 
    /// code 
    aFunctionCall(JOHN_DOE); 
    /// more code 
} 

は私に

void bar (std::string arg2 ) 

私はgrepを/ vimの/ UNIXシェルスクリプトでキャッチしたいと考えてアルゴリズムを与えるべきだろうおそらく最高使用C/C++の解析を試みるのではなく、字下げと書式設定の前提条件が必要です。

ご意見ありがとうございます。

答えて

2

。理由は次のとおりです。

まず、行を検索する必要があります。問題はありませんが、vimでは、文字クラスに_を追加すると、新しい行を含めるよう指示されます。 {_。*}は、複数の行にまたがる括弧の間のすべてに一致します。

これで、機能ヘッダーのパターンが何であれ一致する必要があります(それが機能しても脆くなります)。と検索文字列の間の任意の行に問題があります。あなたの検索文字列に一致します。だから、

/^\(void \+\a\+ *(.*)\)\_.*JOHN_DOE 

のような正規表現を持っているかもしれないが、何が起こることは初めてのVimは関数ヘッダーを見つけている、それがマッチングを開始します。 は、すべての文字がと一致するまでJOHN_DOEを見つけます。ファイル内のすべての関数ヘッダーが含まれます。

私が知る限り、この正規表現パターン以外のすべての文字にvimに一致するように指示する方法はありません。たとえあったとしても、正規表現はこの仕事のツールではありません。それはハンマーでビールを開けるようなものです。私たちがするべきことは、あなたにこの情報を与える簡単なスクリプトを書くことです。

あなたがしたいと、それは、デバッグを共有し、クトゥルフ本人の口から吐き出す正規表現よりも、再利用する方法が簡単です結果を与える必要があります
fun! FindMyFunction(searchPattern, funcPattern) 
    call search(a:searchPattern) 
    let lineNumber = line(".") 
    let lineNumber = lineNumber - 1 
    "call setpos(".", [0, lineNumber, 0, 0]) 

    let lineString = getline(lineNumber) 
    while lineString !~ a:funcPattern 
    let lineNumber = lineNumber - 1 
    if lineNumber < 0 
     echo "Function not found :/" 
    endif 
    let lineString = getline(lineNumber) 
    endwhile 

    echo lineString 

endfunction 

1

タフコールは、私がこの素晴らしいVIM Regex Tutorialを提案する出発点ですが。

1

コードは正規表現ではないので、正規表現ではそれを確実に行うことはできません。問題の言葉には本当のパーサが必要です。

1

uが、それは再帰的にあなたが事実上のテキスト表現が含まれている機能を見つけるために、次のコードを使用することができ、現在のディレクトリから

を開始するファイル内の「JOHN_DOE」を探しますgrep -r -n -H JOHN_DOE *を使用することができます。

public void findFunction(File file, String expression) { 
    Reader r = null; 
    try { 
     r = new FileReader(file); 
    } catch (FileNotFoundException ex) { 
     ex.printStackTrace(); 
    } 
    BufferedReader br = new BufferedReader(r); 

    String match = ""; 
    String lineWithNameOfFunction = ""; 

    Boolean matchFound = false; 

    try { 
     while(br.read() > 0) { 
      match = br.readLine(); 
      if((match.endsWith(") {")) || 
        (match.endsWith("){")) || 
        (match.endsWith("()")) || 
        (match.endsWith(")")) || 
        (match.endsWith("()"))) { 
       // this here is because i guessed that method will start 
       // at the 0 
       if((match.charAt(0)!=' ') && !(match.startsWith("\t"))) { 
        lineWithNameOfFunction = match;       
       } 
      } 

      if(match.contains(expression)) { 
       matchFound = true; 
       break; 
      } 
     } 
     if(matchFound) 
      System.out.println(lineWithNameOfFunction); 
     else 
      System.out.println("No matching function found"); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

私はこれをJAVAで書いてテストし、魅力的に動作します。しかし、欠点はほとんどありませんが、まずはそれは問題ありません。同じ表現を含む複数の関数や多分いくつかの他のもののサポートを追加しませんでした。それを試してみてください。

+0

関数名はどこから来たのですか? –

+0

はい、上記のコードから来るはずですが、grepコマンドで関数の名前を取得できませんでした。 –

0

ロバートのようにRegexが役立つと語った。コマンドモードで、 "/"文字の後にあなたの正規表現を入力して、正規表現の検索を開始します。

Ctags 1もご利用いただけます。プロジェクトのタグファイルを生成することができます。このタグファイルは、「CTRL +」を使用して別のファイル内にあっても、関数呼び出しからその定義に直接ジャンプすることができます。

1

この種のものについては、再び原始的な検索になりますが、私はcompviewプラグインをお勧めします。検索ウィンドウが開き、検索が行われた行全体が表示され、自動的にその行にジャンプすることができます。すばらしい概要を示します。私の知る限りでは、これを行うことができない

alt text http://axisym3.net/jdany/wp-content/images/compview.jpg

1

Arggh!

stdin、stripコメント、およびput関数本体を同じ行にフィルターする小さなプログラムです。それは他のもののほかに、クラス宣言内の名前空間と関数定義にだまされるでしょう。しかし、それは良いスタートかもしれません。そして、そうちょうどそれファイルで、そのCの++

#include <stdio.h> 
#include <assert.h> 

int main() { 
    enum { 
     NORMAL, 
     LINE_COMMENT, 
     MULTI_COMMENT, 
     IN_STRING, 
    } state = NORMAL; 
    unsigned depth = 0; 
    for(char c=getchar(),prev=0; !feof(stdin); prev=c,c=getchar()) { 
     switch(state) { 
     case NORMAL: 
      if('/'==c && '/'==prev) 
       state = LINE_COMMENT; 
      else if('*'==c && '/'==prev) 
       state = MULTI_COMMENT; 
      else if('#'==c) 
       state = LINE_COMMENT; 
      else if('\"'==c) { 
       state = IN_STRING; 
       putchar(c); 
      } else { 
       if(('}'==c && !--depth) || (';'==c && !depth)) { 
        putchar(c); 
        putchar('\n'); 
       } else { 
        if('{'==c) 
         depth++; 
        else if('/'==prev && NORMAL==state) 
         putchar(prev); 
        else if('\t'==c) 
         c = ' '; 
        if(' '==c && ' '!=prev) 
         putchar(c); 
        else if(' '<c && '/'!=c) 
         putchar(c); 
       } 
      } 
      break; 
     case LINE_COMMENT: 
      if(' '>c) 
       state = NORMAL; 
      break; 
     case MULTI_COMMENT: 
      if('/'==c && '*'==prev) { 
       c = '\0'; 
       state = NORMAL; 
      } 
      break; 
     case IN_STRING: 
      if('\"'==c && '\\'!=prev) 
       state = NORMAL; 
      putchar(c); 
      break; 
     default: 
      assert(!"bug"); 
     } 
    } 
    putchar('\n'); 
    return 0; 
} 

「ストリッパー」という名前のファイルにそれをコンパイルし、そして:

cat my_source.cpp | ./stripper | grep JOHN_DOE 

ので、入力を考慮してください。

int foo (int arg1) 
{ 
    /// code 
} 
void bar (std::string arg2 ) 
{ 
    /// code 
    aFunctionCall(JOHN_DOE); 
    /// more code 
} 

"cat example.cpp | ./stripper" の出力は、次のとおりです。

int foo (int arg1) { } 
void bar (std::string arg2){ aFunctionCall(JOHN_DOE); } 

cat example.cpp | ./stripper | grep JOHN_DOE」の出力は、次のとおりです。

void bar (std::string arg2){ aFunctionCall(JOHN_DOE); } 

(「(」を前に置くために、その最後の識別子を推測)関数名を見つけるのジョブは、読者への課題として残されています。

3

私はおそらくこれのために投票されるでしょう!

私は熱心な(G)VIMユーザーですが、私はSource Insightを使用していくつかのコードをレビューしたり理解したりしたいと思っています。私は実際のエディタとして使用することはほとんどありません。

このケースでは、これはまさにあなたが望むものです。 ...関係ウィンドウで...など/定数/定義/いくつかのデータ型を強調し使用するすべての関数/メソッドを示し

gif of the relations window from the source insight website http://www.sourceinsight.com/docs35/ae1183f1.gif

痛いです!私の担当者が行く。

+0

心配しないで、それは私のupvoteを取り除くためにいくつかのdownvotesを取るでしょう。確かにWhaledawg vimscriptが好きです。なぜなら、これは質問にほぼ正確にマッチするからですが、これには追加のソフトウェアが必要です。 – Andy

関連する問題