2016-09-21 5 views
0

javascriptファイルから特定の関数とその本体をテキストとして取り出し、その関数をC#を使用して出力として出力する必要があります。関数名とjsファイルを入力パラメータとして与える必要があります。私は正規表現を使用してみましたが、希望の結果を達成できませんでした。ここで正規表現のコードです。C#を使用してJavaScriptファイルから関数名と本体コードを取得する

public void getFunction(string jstext, string functionname) 
{ 
    Regex regex = new Regex(@"function\s+" + functionname + @"\s*\(.*\)\s*\{"); 
    Match match = regex.Match(jstext); 
} 

これを行う方法は他にありますか?

+0

私はあなたがJavascriptを十分*定期*であることを見つけるとは思いません。私はこれを維持せずに行う方法を考えることができません文字列やjavascriptの正規表現の中に一致しない '}'が現れるかどうかを考慮する必要があります。関数についての前提を盛り込んでいない限り、おそらく[.net]の既存のjavascriptパーサーを調べるべきです(http://stackoverflow.com/questions/14355910/javascript-parser-and-analyzer-in- c-sharp-net-4-5)。 –

+0

define: 'couldntは望ましい結果を達成しました。 ' – Jamiec

+0

' var functionName = function(x){...} 'のような関数をサポートする必要がありますか? 'window ['function' + name] = function(x){...}'はどうでしょうか? –

答えて

0

この回答は、コメントで提供する前提に基づいており、C#関数は関数式の検索ではなく、関数式の検索にのみ必要であることを前提としています。

コメントで指摘したように、javascriptは複雑すぎて、正規表現で効率的に表現できません。関数の最後に到達したことを知る唯一の方法は、大括弧がすべて一致していることです。それでも、エスケープ文字、コメント、および文字列を考慮する必要があります。

これを達成するために考えられる唯一の方法は、関数本体の先頭から括弧が一致するまで、実際にすべての1文字を繰り返して、奇妙な何かを追跡することです。

このような解決策は決して非常にきれいにはなりません。私はどのように動作するかの例をまとめましたが、javascriptがちょっとした癖や落とし穴で詰まっていることを知っているので、ここでは考慮されていないコーナーケースがたくさんあると私は確信しています。私はそれが少しきちんと作られることも確信しています。

私の最初の実験から

、(つまり、/で区切られた)文字、マルチおよびシングルラインコメントは、「で区切られた文字列、 'や `、および正規表現をエスケープ処理する必要があり、次の。

これがなければなりません私は人々がコメントで思い付くことができるかの例外を見て興味をそそらだが、かなり遠くにあなたを得る:

private static string GetFunction(string jstext, string functionname) { 

    var start = Regex.Match(jstext, @"function\s+" + functionname + @"\s*\([^)]*\)\s*{"); 

    if(!start.Success) { 
     throw new Exception("Function not found: " + functionname);  
    } 

    StringBuilder sb = new StringBuilder(start.Value); 
    jstext = jstext.Substring(start.Index + start.Value.Length); 
    var brackets = 1; 
    var i = 0; 

    var delimiters = "`/'\""; 
    string currentDelimiter = null; 

    var isEscape = false; 
    var isComment = false; 
    var isMultilineComment = false; 

    while(brackets > 0 && i < jstext.Length) { 
     var c = jstext[i].ToString(); 
     var wasEscape = isEscape; 

     if(isComment || !isEscape) 
     { 
      if(c == @"\") { 
       // Found escape symbol. 
       isEscape = true; 
      } else if(i > 0 && !isComment && (c == "*" || c == "/") && jstext[i-1] == '/') { 
       // Found start of a comment block 
       isComment = true; 
       isMultilineComment = c == "*"; 
      } else if(c == "\n" && isComment && !isMultilineComment) { 
       // Found termination of singline line comment 
       isComment = false; 
      } else if(isMultilineComment && c == "/" && jstext[i-1] == '*') { 
       // Found termination of multiline comment 
       isComment = false; 
       isMultilineComment = false; 
      } else if(delimiters.Contains(c)) { 
       // Found a string or regex delimiter 
       currentDelimiter = (currentDelimiter == c) ? null : currentDelimiter ?? c; 
      } 

      // The current symbol doesn't appear to be commented out, escaped or in a string 
      // If it is a bracket, we should treat it as one 
      if(currentDelimiter == null && !isComment) { 
       if(c == "{") { 
        brackets++; 
       } 
       if(c == "}") { 
        brackets--; 
       } 
      } 

     } 

     sb.Append(c); 
     i++; 

     if(wasEscape) isEscape = false; 
    } 


    return sb.ToString(); 
} 

Demo

関連する問題