web-dev-qa-db-ja.com

テキスト内のコードを確実に検出する簡単な方法は?

GMailにはこの機能があり、thinksに添付ファイルがある可能性があることをメールで送信しようとすると警告が表示されます。

Did you mean to attach files?

GMailはメールでsee the attachedという文字列を検出しましたが、実際の添付ファイルは検出しなかったため、[送信]ボタンをクリックすると、OK /キャンセルダイアログが表示されます。

スタックオーバーフローに関連する問題があります。つまり、ユーザーが投稿を入力すると これのように

私の問題は、データベースを変更する必要があるのですが、
新しい接続を作成することはありません。例:
 
 DataSet dsMasterInfo = new DataSet(); 
 Database db = DatabaseFactory.CreateDatabase( "ConnectionString"); 
 DbCommand dbCommand = db.GetStoredProcCommand( " uspGetMasterName "); 

このユーザーはコードをcodeとしてフォーマットしませんでした!

つまり、Markdownごとに4つのスペースでインデントしたり、コードボタン(またはキーボードショートカット)を使用していません。 ctrl+k)それは彼らのためにそれを行います。

したがって、私たちのシステムは多くの編集を受け入れており、人々はそこに行って、どういうわけかこれを理解することができない人々のためにコードを手動でフォーマットする必要があります。これは 大量の攻撃 につながります。エディターのヘルプを何度か改善しましたが、ユーザーの家まで車で行き、キーボードの適切なボタンを押すのではなく、次に何をすべきかわからなくなりました。

これが、Google GMailスタイルの警告を検討している理由です。

コードを投稿するつもりでしたか?

コードのように思われるものを記述しましたが、ツールバーのコードボタンまたは ctrl+k コードフォーマットコマンド。

ただし、この警告を表示するには、質問内のフォーマットされていないコードと思われるものの存在を検出する必要があります。これを行う簡単で信頼できる方法は何ですか?

  • Markdown の場合、コードは常に4つのスペースまたはバッククォートでインデントされるため、正しくフォーマットされたものはすべてチェックからすぐに破棄できます。
  • これは単なる警告であり、最初の質問をする(または最初の回答を提供する)評判の低いユーザーにのみ適用されるため、誤検出が発生しても問題ありません。約5%以下です。
  • スタックオーバーフローに関する質問は、任意の言語で作成できますが、実際には、チェックを「ビッグテン」言語に制限することができます。 C#、Java、PHP、JavaScript、Objective-C、C、C++、Python、Rubyなどのタグページごと。
  • Stack Overflowクリエイティブコモンズデータダンプ を使用して潜在的なソリューションを監査し(または Stack Overflowのトップ10タグ でいくつかの質問を選択)、その方法を確認します。
  • 疑似コードは問題ありませんが、さらに使いやすくしたい場合はc#を使用します。
  • シンプルな方が良いです(機能する限り)。接吻!あなたのソリューションが10の異なるコンパイラーで投稿をコンパイルすることを試みる必要がある場合、またはベイジアン推論エンジンを手動でトレーニングするために多くの人々がいる場合、それは...私たちが考えていたものとは厳密には異なります。
144
Jeff Atwood

適切な解決策はおそらくいくつかの学習/統計モデルでしょうが、ここにいくつかの楽しいアイデアがあります:

  1. 行末のセミコロン。これだけでもたくさんの言語を捕まえるでしょう。
  2. テキストを直接区切るためのスペースなしのテキストを括弧で囲みます:myFunc()
  3. 2つの単語間のドットまたは矢印:_foo.bar = ptr->val_
  4. 中括弧、角括弧の存在:while (true) { bar[i]; }
  5. 「コメント」構文の存在(/ *、//など):_/* multi-line comment */_
  6. 珍しい文字/演算子:_+, *, &, &&, |, ||, <, >, ==, !=, >=, <=, >>, <<, ::, ___
  7. テキストに対して構文ハイライターを実行します。かなり高い割合で強調表示される場合は、おそらくコードです。
  8. 投稿内のキャメルケースのテキスト。
  9. ネストされた括弧、中括弧、および/または大括弧。

これらのそれぞれが出現する回数を追跡することができ、これらは perceptron のような機械学習アルゴリズムの機能として、SpamAssassinと同じように使用できます。

148

片側で書かれた英語の平均的なメトリックと、もう片側でのコードを知りたいと思います。

  • 段落の長さ
  • 行の長さ
  • 言葉の大きさ
  • 使用される文字
  • アルファベット、数字、その他の記号文字の比率
  • ワードあたりのシンボル数
  • 等.

たぶんそれだけですでにコードと残りの部分を区別できるかもしれません。少なくとも、コードは、言語に関係なく、多くの場合、いくつかの著しく異なるメトリックを表示すると信じています。

良いニュースは、統計を作成するための十分なデータがすでにあることです。


さて、仮定をバックアップするためのデータをいくつか用意しました。 :-)

私はあなた自身の投稿と StackOverflowで見つけた最初の投稿 で、かなり高度なツールであるwcを使って、簡単なテストを行いました。

これらの2つの例のテキスト部分とコード部分でwcを実行した後のコードは次のとおりです。

まず、英語の部分を見てみましょう:

  • 投稿の英語部分(2635文字、468ワード、32行)
    • 5文字/単語、82文字/行、14単語/行
  • 他の投稿の英語部分(1499文字、237ワード、12行)
    • 6文字/単語、124文字/行、19単語/行

かなり似ていると思いませんか?

コード部分を見てみましょう!

  • 投稿のコード部分(174文字、13ワード、3行)
    • 13文字/単語、58文字/行、4単語/行
  • 他の投稿のコード部分(4181文字、287ワード、151行)
    • 14文字/単語、27文字/行、2単語/行

これらのメトリックがどれほど異なっていないか、さらに重要なことに、それらが英語のメトリックとどれほど異なっているかを確認してください。そして、これは限られたツールを使用しているだけです。より多くのメトリックを測定することで、本当に正確な値を取得できると確信しています(特にchars統計について考えています)。

私はクッキーを持っていますか?

54

通常、マルコフチェーンはテキストの生成に使用されますが、トレーニング済みモデルに対するテキストの類似性( C.E。Shannon 195 ごと)の予測にも使用できます。複数のマルコフ連鎖をお勧めします。

普及している言語ごとに、その言語のコードの大規模で代表的なサンプルでマルコフ連鎖をトレーニングします。次に、コードを検出するスタックオーバーフローポストについて、チェーンごとに次の操作を行います。

  • 投稿の行をループします。
    • 2つの変数を宣言します:ACTUAL = 1.0およびHIGHEST = 1.0
    • 行の各文字をループします。
      • 各文字について、現在の文字が前のN文字に続く文字である確率をマルコフ連鎖で見つけます。セットACTUAL = ACTUAL * PROB1。現在の文字がチェーンに存在しない場合は、PROBに小さな値を使用します1、0.000001など。
      • 次に、前のN文字に続く可能性が最も高い(つまり、最も高い確率の)文字を見つけます。 HIGHEST = HIGHEST * PROBに設定2
      • 明らかに、PROB2 > =確率1

行ごとに、実際の値と最高の値が必要です。 ACTUALをHIGHESTで割ります。これにより、特定の行がソースコードであるかどうかに関する適合度スコアが得られます。これにより、指定した例の各行に番号が関連付けられます。

my problem is I need to change the database but I don't won't to create // 0.0032
a new connection. example: // 0.0023

DataSet dsMasterInfo = new DataSet(); // 0.04
Database db = DatabaseFactory.CreateDatabase("ConnectionString");   // 0.05
DbCommand dbCommand = db.GetStoredProcCommand("uspGetMasterName");  // 0.04

最後に、投稿にコードがある場合を決定するしきい値を選択する必要があります。これは単に、高性能によって得られる観察によって選択された数である可能性があります。また、高得点の行数を考慮に入れることもできます。

トレーニング

トレーニングするには、言語のコードの大規模で代表的なサンプルを入手してください。コードテキストをループし、ファイル内の各Nグラム(Nの範囲はパラメーター化する必要があります)を後続の文字の統計頻度に関連付けるプログラムを記述します。これにより、バイグラムに続く複数の可能な文字の状態が生成され、それぞれに確率が関連付けられます。たとえば、バイグラム「()」には、次のような文字確率があります。

"()" 0.5-> ";"
"()" 0.2-> "."
"()" 0.3-> "{"

最初は、たとえば、「セミコロンが空の括弧内に続く確率は0.5です。」と読む必要があります。

トレーニングには、サイズが2〜5のN-gramをお勧めします。 これについていくつかの調査を行ったとき 、N-gramのサイズ2から5が英語に適していることがわかりました。ソースコードの多くは英語に似ているので、まずはその範囲から始めて、適切に機能するものを見つけたら、最適なパラメーター値を見つけるように調整することをお勧めします。

警告:モデルは識別子、メソッド名、空白などの影響を受けます。ただし、トレーニングを調整して、トレーニングサンプルの特定の機能を省略できます。たとえば、不要な空白をすべて折りたたむことができます。入力(スタックオーバーフローポスト)内の空白の存在も無視できます。アルファベットの大文字小文字の区別も無視できます。これは、さまざまな識別子の名前付け規則に直面した場合により弾力性があります。

私の調査 の間に、私たちの方法はスペイン語だけでなく英語でもうまく機能することがわかりました。これがソースコードでもうまく機能しない理由はわかりません。ソースコードは人間の言語よりもさらに構造化され、予測可能です。

23
Matthew Rodatus

根本的に異なるアプローチを提案できますか? SO許可される唯一の人間の言語は英語なので、英語以外のものはすべて、コードスニペットである可能性が99.9%です

だから私の解決策は:世の中にある多くの英語の言語チェッカーの1つを使用することです(スペルミス以外に、二重ドットなどの構文の誤り、または#~などの非言語記号も通知することを確認してください)。次に、大量のエラーと警告をスローする行/段落は、「これはコードですか?」質問。

もちろん、このアプローチは、英語以外の言語を使用するStackExchangeサイトにも適応できます。

ちょうど私の2¢...

13
mac

すべてのプログラミング言語が「[]」、「;」、「()」などの特殊文字に依存しているため、疑似コードは本当の課題をもたらします。これらの特殊文字の出現を数えるだけです。バイナリファイルを検出するのと同じように(サンプルの5%以上にバイト値0が含まれています)。

11
Ivo Limmen

私はおそらくこれについていくつかの反対票を獲得するつもりですが、あなたは間違った角度からこれに取り組んでいると思います。

この行は私を手に入れました:

人々は、何らかの形でこれを理解することができない人々のために入り、手動でコードをフォーマットする必要があります

その立場は一種の傲慢であるというIMO。これは、問題がユーザーではなくソフトウェア自体、または少なくともUIであるときに、ソフトウェアの適切な使用方法を理解できないユーザーにプログラマーやデザイナーが迷惑をかけるソフトウェア設計で多く見られます。

この問題の根本的な原因はユーザーではありませんが、ユーザーがこれを実行できるかどうかは明らかではありません。

これをより明確にするためのUIの変更はどうですか?きっとこれは:

  1. 新しいユーザーが何をする必要があるかをより明確に
  2. 複雑なアルゴリズムを記述して複数の言語のコードロジックを検出するよりも、構築が簡単

例:

enter image description here

11
matt_asbury

特定の言語のみを対象にする必要があるかもしれません。英語に非常に似た言語を取得できるため、一般的にこの問題は扱いにくい可能性があります(例: inform7 )。しかし幸いにも、最もよく使われるものはかなり簡単にカバーできました。

私の最初のカットは、C、C++、Java、C#、および同様の構文を使用し、非常に単純な他の言語に適切に一致するシーケンス ";\n"を探すことです。また、英語よりも英語で使用される可能性が低くなります。改行なし

4
jk.

誰かがタグを見て、そのための構文を探すことに言及しましたが、これは新しいユーザーを対象としているため、撃墜されました。

考えられるより良い解決策は、質問の本文で言語名を探し、同じ戦略を適用することです。私が「Javascript」、「Java」、または「C#」に言及する場合、それはおそらくそれが問題であり、問​​題のコードはその言語である可能性が高いです。

4
Omar Kooheji

まず、スペルチェックを実行します。適切な英語の単語はほとんど見つかりませんが、スペルチェッカーが分割するように提案する単語はたくさんあるはずです。

次に、通常の英語では一般的ではない、コードでは一般的な句読点/特殊文字があります。

  • something();は単純な英語にはできません。
  • $somethingここで、somethingはすべて数値ではありません。
  • ->スペースなしの単語の間;
  • .単語間のスペースなし

もちろん、それをうまく機能させるために、これらの特性に基づいてベイズ分類器を構築することもできます。

1
vartec

同様の構文を共有する言語のセットがいくつかあります。ほとんどの言語はいくつかの言語の影響を受けているため、言語[AMPL、AWK、csh、C++、C-、C#、Objective-C、BitC、D、Go、Java、JavaScript、Limbo、LPC、Perl、PHP、 Pike、Processing [はすべてCの影響を受けたため、Cを検出すると、これらすべての言語が検出されます。したがって、この言語セットを検出するための簡単なパターンを書くだけで済みます。

ほとんどのコードはポストの他のテキストブロックから2つの改行または類似の行で分割されるため、テキストもブロックに分割します。

これはjavascript(cファミリの非常に単純な不完全なサンプル)で簡単に実行できます。

var txt = "my problem is I need to change the database but I don't won't to create a new connection. example:\n\nDataSet dsMasterInfo = new DataSet();Database db = DatabaseFactory.CreateDatabase(&quot;ConnectionString&quot;);DbCommand dbCommand = db.GetStoredProcCommand(&quot;uspGetMasterName&quot;);";
var blocks = txt.split(/\n\n/gi); console.dir(blocks);
var i = blocks.length;
var cReg = /if\s*\(.+?\)|.*(?:int|char|string|short|long).*?=.+|while\s*\(.+?\)/gi;

while ( i-- ){
   var current = blocks[i];
   if ( cReg.test( current ) ){
      console.log("found code in block[" +  i + "]");
   }
}
1

他の言語(現在最も使用されているプログラミング言語とは少し異なるように見える)が普及し、現在使用されている言語の人気が低下するため、最も将来性があり、手動での調整が最小限で済む可能性があります。 abやa()などの特定のものを探すのではなく、 Google Translateが行うこと (「どのように機能するか」というタイトルの段落を参照)のようなもの。

言い換えれば、探すコードのパターンを手動で考える代わりに、コンピュータはそれ自体でそれを理解することができます。これは、

  1. 多くの異なるプログラミング言語の多くのコード

    • 提案:Google CodeやGithubなどのWebベースのソースコードリポジトリから、またはすでにコードとしてマークされているStackoverflow上のものからコードサンプルを自動的に取得します

    • 注:コードのコメントを解析することをお勧めします

  2. ウェブ上の記事から取られたたくさんの英語のテキスト

    • プログラミングに関する記事からではありませんが(そうでなければ、コードが含まれている可能性があり、システムを混乱させる可能性があります:-))

そして、ある種のアルゴリズムを自動的にコード内で英語以外のパターンを見つけ、その逆を行い、それらのパターンを使用して、何がコードで何がコードではないかを検出します投稿に対してアルゴリズムを実行します。

(ただし、このようなアルゴリズムがどのように機能するかはわかりません。現在の質問に対する他の回答には、そのための有用な情報があるかもしれません。)

その後、システムは時々コードを再スキャンして、その時点でのコードの見え方の変化を明らかにすることができます。

0
Abbafei

各行の単語/句読文字を数えるだけです。英語は4以上、コードは2未満になる傾向があります。

たとえば、上の段落には18語と4つの句読点があります。この段落には19語と4句読点があるので、予想内です。

もちろん、これは初心者の英語がわからないスピーカーの質問に対してテストする必要があり、それらのケースでは、統計が歪んでいる可能性があります。

[non-whitespace]。[whitespace or newline]はコードでは非常にまれですが、英語では一般的であるため、これは句読点ではなく単語としてカウントされる可能性があります。

最大の問題は、誰かが次のような質問をするインラインコードだと思います。

(i = 0; i> 100; i ++){}の場合、どういう意味ですか?

これはコードと英語であり、バックティックと同様にマークアップする必要があります。

for (i=0; i>100; i++) {}と言ったら、どういう意味ですか?

0
rjmunro

最初に、実際にそのように指定するだけで十分な(十分に)書式設定されたコードと、(あまりに)手動で書式設定が必要な(あまりに)書式が不十分なコードを区別する必要があると思います。

書式付きコードにはブレークラインとインデントがあります。つまり、行の前に単一のブレークラインがある場合は、良い候補です。その上に先頭の空白がある場合は、非常に良い候補があります。

通常のテキストでは、書式設定に2つのブレークラインまたは2つのスペースと1つのブレークラインを使用しているため、明確に区別できる基準があります。

LISPコードではセミコロンは見つかりません、Rubyコードでは括弧が見つからない、疑似コードではほとんど見つからない可能性があります。しかし、(非難解な)言語ではブレークラインとインデントでフォーマットされるまともなコード。これほど普遍的なものはありません。最終的にコードは、人間が読むように書かれているからです。

したがって、まずコードの潜在的なを検索です。また、通常、コード行はグループに分けられます。ある場合は、上または下の行もコード行である可能性が高いです。

コードの潜在的な行を特定したら、次のことができますそれらを定量化可能な基準に対してチェックし、いくつかのしきい値を選択します

  • word以外の文字の頻度
  • 識別子の頻度:CamelCaseまたはunder_scoreスタイルの非常に短い単語または非常に長い単語
  • 珍しい言葉の繰り返し

また、プログラマーとcsがいるので、stackoverflowのスコープが明らかに絞り込まれています。すべての言語タグを言語として表記することを検討してください。そして投稿するときは、少なくとも1つの言語タグを選択するか、language-agnosticタグまたは明示的に省略します。

最初のケースでは、どの言語を検索するかがわかっており、2番目のケースでは、疑似コードを検索したい場合があり、最後のケースでは、コードが存在しない可能性があります。フレームワークなど。

0
back2dos

検出する言語ごとにパーサーを作成し(通常、ANTLRの言語定義は簡単に見つけることができます)、質問の各行を各パーサーで実行します。行が正しく解析される場合は、おそらくコードがあります。

これに関する問題は、一部の英語(自然言語)の文がコードとして解析される可能性があるため、他のアイデアも含める必要がある場合や、1行または2行以上の連続した行が同じ言語パーサー。

他の潜在的な問題は、これがおそらく疑似コードを取得しないことですが、それは問題ないかもしれません。

0
Jeff Knecht