2

テキストを含む文字列があります。テキストは、コードである場合とそうでない場合があります。Github の Linguist を使用して、候補のリストを指定した場合にのみ、可能性の高いプログラミング言語を検出できました。

# test_linguist_1.rb
#!/usr/bin/env ruby

require 'linguist'

s = "int main(){}"
candidates = [Linguist::Language["Python"], Linguist::Language["C"], Linguist::Language["Ruby"]]
b = Linguist::Blob.new('', s)
langs = Linguist::Classifier.call(b, candidates)
puts langs.inspect

実行:

$ ./test_linguist_1.rb 
[#<Linguist::Language name=C>, #<Linguist::Language name=Python>, #<Linguist::Language name=Ruby>]

候補のリストを与えたことに注意してください。 候補のリストを定義する必要がないようにするにはどうすればよいですか?

私は次のことを試しました:

# test_linguist_2.rb
#!/usr/bin/env ruby

require 'linguist'

s = "int main(){}"
candidates = Linguist::Language.all
# I also tried only Popular
# candidates = Linguist.Language.popular
b = Linguist::Blob.new('', s)
langs = Linguist::Classifier.call(b, candidates)
puts langs.inspect    

実行:

$ ./test_linguist_2.rb 
/home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:131:in `token_probability': undefined method `[]' for nil:NilClass (NoMethodError)
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:120:in `block in tokens_probability'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:119:in `each'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:119:in `inject'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:119:in `tokens_probability'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:105:in `block in classify'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:104:in `each'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:104:in `classify'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:78:in `classify'
from /home/marvelez/.rvm/gems/ruby-2.2.1/gems/github-linguist-4.8.9/lib/linguist/classifier.rb:20:in `call'
from ./test_linguist.rb:21:in `block in <main>'
from ./test_linguist.rb:14:in `each'
from ./test_linguist.rb:14:in `<main>'

追加:

  1. これは Github Linguist を使用する最良の方法ですか? FileBlob は Blob の代替ですが、これには文字列をファイルに書き込む必要があります。これは 2 つの理由で問題があります。1) 遅い、2) 選択されたファイル拡張子が言語学者をガイドし、正しいファイル拡張子がわからない。
  2. これを行うためのより良いツールはありますか? Github Linguist はおそらくファイルに対しては適切に機能しますが、文字列に対しては機能しません。
4

2 に答える 2

5

Linguist のソース コードをざっと見てみると、言語を判別するために多くの戦略を使用しているように見え、各戦略を順番に呼び出します。Classifierは、呼び出される最後の戦略であり、その時点までに、以前の戦略から言語の「候補」 (ご自分で発見したように) を (うまくいけば) 選択しています。したがって、あなたが私たちと共有した特定のサンプルについては、ファイルが実際に存在しない場合でも、何らかのファイル名、または言語候補のリストを渡す必要があると思います。どちらも選択できない場合、これは問題の実行可能な解決策ではない可能性があります。

$ ruby -r linguist -e 'p Linguist::Blob.new("foo.c", "int main(){}").language'
#<Linguist::Language name=C>

nilファイル名なしで、#<Linguist::Language name=C++>「foo.cc」と同じコード サンプルを返します。

良いニュースは、テストに本当に悪いサンプルを選んだことです. :-) 他の戦略はモードラインとシバンに注目するため、より複雑なサンプルほど成功する可能性が高くなります。これらを見てください:

$ ruby -r linguist -e 'p Linguist::Blob.new("", "#!/usr/bin/env perl
print q{Hello, world!};
").language'
#<Linguist::Language name=Perl>
$ ruby -r linguist -e 'p Linguist::Blob.new("", "# vim: ft=ruby
puts %q{Hello, world!}
").language'
#<Linguist::Language name=Ruby>

ただし、シバンまたはモードラインがない場合は、まだ運が悪いです。インストール時に計算されてディスクにシリアル化され、言語検出中に自動的に読み込まれるトレーニング データセットがあることがわかりました。残念ながら、このステップに到達するまでに候補がない場合、このトレーニング データセットを使用できないというバグがライブラリにあると思います。バグを修正すると、次のことが可能になります。

$ ruby -Ilib -r linguist -e 'p Linguist::Blob.new("", "int main(){}").language'
#<Linguist::Language name=XC>

(XC が何であるかはわかりませんが、文字列に#include <stdio.h>orなどの他のトークンを追加すると、 int argc, char* argv[]C が得られます。ほとんどのサンプルには、分析する肉がさらにあると確信しています。)

これは非常に簡単な修正であり、PRを提出しました。それまでの間、よろしければ私のジェムのフォークを使ってください。それ以外の場合は、Linguist::Classify を直接使用することを検討する必要がありますが、これは面倒なことになる可能性があります。

私のフォークを使用するには、Gemfile を次のように追加/変更します。

gem 'github-linguist',
  require: 'linguist',
  git: 'https://github.com/mwpastore/linguist.git',
  branch: 'fix-no-candidates'

PRがマージされ、修正された新しいバージョンのGemがリリースされたら、この回答を更新して更新しようとします。リポジトリのガイドラインを満たすため、および/またはメンテナーを満足させるために強制プッシュを行う必要がある場合はbundler update、変更を反映するために a を行う必要がある場合があります。ご不明な点がございましたら、お知らせください。

于 2016-09-09T00:21:26.753 に答える
-1

言語学者のソースをもう一度ざっと見てみると、Linguist::Language.all探しているもののようです。

編集:Linguist::Language.all自分で試しました。この失敗は、さらに別のバグによるものです。一部の言語では、データに問題があるようです。たとえば、これも失敗します。

candidates = [Linguist::Language['ADA']]

これは明らかに にlib/linguist/samples.jsontokens.ADA存在しないためです。そのような言語はこれだけではありません。

バグを回避するために、言語をフィルタリングできます。

non_buggy_languages = Linguist::Samples.cache['tokens'].keys
candidates = non_buggy_languages.map { |l| Linguist::Language[l] }
于 2016-09-09T01:19:47.373 に答える