it-swarm-tr.com

Metindeki kodu güvenilir bir şekilde tespit etmek için basit bir yöntem?

GMail, düşünüyor bir eki olabileceğini belirten bir e-posta göndermeye çalıştığınızda sizi uyaracağı bu özelliğe sahiptir.

Did you mean to attach files?

GMail see the attached e-postada, ancak gerçek bir ek yok, Gönder düğmesini tıkladığımda bir Tamam/İptal iletişim kutusu ile beni uyarıyor.

Stack Overflow ile ilgili bir sorunumuz var. Bir kullanıcı bir gönderi girdiğinde bunun gibi :

 sorunum veritabanını değiştirmem gerekiyor ama yeni bir bağlantı oluşturmayacağım 
. örnek: 
 
 DataSet dsMasterInfo = yeni DataSet (); 
 Veritabanı db = DatabaseFactory.CreateDatabase ("ConnectionString"); 
 DbCommand dbCommand = db.GetStoredProcCommand (" uspGetMasterName "); 

Bu kullanıcı kodunu kod ! olarak biçimlendirmedi

Yani, Markdown başına 4 boşluk girintilemediler veya kod düğmesini (veya klavye kısayolunu) kullanmadılar ctrl+k) bunu onlar için yapar.

Böylece, sistemimiz insanların girmesi gereken bir çok düzenlemeyi kabul ediyor ve bunu bir şekilde anlayamayan insanlar için kodu manuel olarak biçimlendiriyor. Bu bir sürü bellyaching yol açar. Editör yardımını birkaç kez geliştirdik, ancak kullanıcının evine gidip klavyelerinde doğru düğmelere basmaktan kısa süre sonra, daha sonra ne yapacağımızı görmüyoruz.

Bu yüzden bir Google GMail stili uyarısı düşünüyoruz:

Kod göndermek mi istediniz?

Kod gibi göründüğünü düşündüğümüz şeyler yazdınız, ancak araç çubuğu kod düğmesini veya 4 alanı girerek kodu boşluk olarak biçimlendirmediniz. ctrl+k kod biçimlendirme komutu.

Ancak, bu uyarının sunulması, bir soruda biçimlendirilmemiş kod olduğunu düşündüğümüz şeyin varlığını belirlememizi gerektirir . Bunu yapmanın basit, yarı güvenilir bir yolu nedir?

  • Markdown başına, kod her zaman 4 boşlukla veya geri tıklamayla girintilidir, bu nedenle doğru biçimlendirilmiş herhangi bir şey hemen çekten atılabilir.
  • Bu sadece bir uyarı ve yalnızca ilk sorularını soran (veya ilk cevaplarını veren) düşük itibarlı kullanıcılar için geçerli olacak, bu yüzden yaklaşık 5 olduğu sürece bazı yanlış pozitifler tamam. % veya daha az.
  • Yığın Taşması ile ilgili sorular any dilinde olabilir, ancak çekimizi diyelim ki "büyük on" dille gerçekçi olarak sınırlayabiliriz. Etiketler sayfası başına C #, Java, PHP, JavaScript, Objective-C, C, C++, Python, Ruby olur.
  • Potansiyel çözümünüzü denetlemek için Stack Overflow reklam öğesi veri dökümünü kullanın (veya Stack Overflow'da en iyi 10 etiket için birkaç soru seçin) ve nasıl olduğunu görün.
  • Pseudocode gayet iyi, ancak ekstra dost olmak istiyorsanız c # kullanıyoruz.
  • Ne kadar basit o kadar iyi (çalıştığı sürece). ÖPMEK! Çözümünüz, 10 farklı derleyicideki yayınları derlemeye çalışmamızı veya bir bayes çıkarım motorunu manuel olarak eğitmek için bir ordu oluşturmayı gerektiriyorsa, bu ... tam olarak aklımızda değil.
144
Jeff Atwood

Uygun bir çözüm muhtemelen bazı öğrenilmiş/istatistiksel model olacaktır, ancak işte bazı eğlenceli fikirler:

  1. Bir satırın sonunda noktalı virgül . Bu tek başına bir sürü dili yakalardı.
  2. Ayırmak için boşluk bırakmadan metni doğrudan takip eden parantezler: myFunc()
  3. İki kelime arasındaki nokta veya ok: foo.bar = ptr->val
  4. Kıvırcık parantezlerin varlığı, parantez: while (true) { bar[i]; }
  5. "Yorum" sözdiziminin varlığı (/ *, // vb.): /* multi-line comment */
  6. Yaygın olmayan karakterler/işleçler: +, *, &, &&, |, ||, <, >, ==, !=, >=, <=, >>, <<, ::, __
  7. Sözdizimi vurgulayıcıyı metin üzerinde çalıştırın. Eğer yüksek bir yüzdesini vurguluyorsa, muhtemelen koddur.
  8. yayındaki metni camelCase.
  9. iç içe parantezler, kaşlı ayraçlar ve/veya köşeli ayraçlar.

Bunların her birinin kaç kez göründüğü takip edilebilir ve bunlar, SpamAssassin'in yaptığı gibi perceptron gibi bir makine öğrenme algoritmasında özellikler olarak kullanılabilir.

148
Yevgeniy Brikman

Bir tarafta yazılı İngilizce'nin ortalama metriklerinin, diğer tarafta kodlamanın ortalama ne olduğunu merak ediyorum.

  • paragraf uzunluğu
  • hat uzunluğu
  • kelimelerin boyutu
  • kullanılan karakter
  • alfabetik, sayısal ve diğer sembol karakterleri arasındaki oran
  • kelime başına sembol sayısı
  • vb.

Belki de bu tek başına kod ve geri kalanı arasında ayrım yapabilir. En azından dilin ne olursa olsun, kodun birçok durumda fark edilir derecede farklı metrikler göstereceğine inanıyorum.

İyi haber şu ki, istatistiklerinizi oluşturmak için zaten çok fazla veri var.


Tamam varsayımları desteklemek için bazı verilerle geri döndüm. :-)

Oldukça gelişmiş bir araçla kendi postanızda ve StackOverflow'da bulduğum ilk yazı hızlı ve kirli bir test yaptım: wc.

Metin kısmında ve bu iki örneğin kod kısmında wc çalıştırdıktan sonra sahip olduğum şey:

Önce İngilizce kısma bakalım :

  • Yayınınızın İngilizce kısmı (2635 karakter, 468 kelime, 32 satır)
    • 5 karakter/Word, 82 karakter/satır, 14 kelime/satır
  • Diğer yazının İngilizce kısmı (1499 karakter, 237 kelime, 12 satır)
    • 6 karakter/Word, 124 karakter/satır, 19 kelime/satır

Oldukça benzer değil mi?

Şimdi kod bölümüne bir göz atalım!

  • Yayınınızın kod kısmı (174 karakter, 13 kelime, 3 satır)
    • 13 karakter/Word, 58 karakter/satır, 4 kelime/satır
  • Diğer yazının kod kısmı (4181 karakter, 287 kelime, 151 satır)
    • 14 karakter/Word, 27 karakter/satır, 2 kelime/satır

Bu metriklerin ne kadar farklı olmadığını, ancak daha da önemlisi, İngilizce metriklerden ne kadar farklı olduklarını görün? Ve bu sadece sınırlı bir araç kullanıyor. Artık daha fazla metrik ölçerek gerçekten doğru bir şey elde edebileceğinizden eminim (özellikle chars istatistiklerini düşünüyorum).

Kurabiyeyi tadabilir miyim?

54
Julien Guertault

Tipik olarak, Markov zincirleri metin oluşturmak için kullanılır, ancak metnin eğitimli bir modelle benzerliğini tahmin etmek için de kullanılabilir (per C.E. Shannon 1950 ). Birden fazla Markov zinciri öneririm.

Her yaygın dil için, Markov zincirini dilde büyük, temsili bir kod örneği üzerinde eğitin. Ardından, kodunu algılamak istediğiniz Yığın Taşması gönderisi için, zincirlerin her biri için aşağıdakileri yapın:

  • Yazıdaki çizgilerden geç.
    • İki değişken bildirin: ACTUAL = 1.0 ve HIGHEST = 1.0
    • Satırdaki her karakteri gözden geçirin.
      • Her karakter için, Markov zincirinde, mevcut karakterin önceki N karakterlerini izleyen karakter olma olasılığını bulun. Ayarla GERÇEK = GERÇEK * PROB1. Geçerli karakter zincirde yoksa, PROB için küçük bir değer kullanın1, 0.000001 gibi.
      • Şimdi, önceki N karakterlerini takip etme olasılığı en yüksek olan karakteri (yani en yüksek olasılık) bulun. EN YÜKSEK = EN YÜKSEK * PROB'u ayarla2.
      • Açıkçası, PROB2 > = PROB1

Her satır için bir GERÇEK ve YÜKSEK değere sahip olmalısınız. ACTUAL öğesini YÜKSEK'e bölün. Bu size belirli bir satırın kaynak kodu olup olmadığı konusunda uygunluk puanı verecektir. Bu, bir sayıyı verdiğiniz örnekteki satırların her biri ile ilişkilendirir:

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

Son olarak, gönderide kodun ne zaman olacağını belirlemek için bir eşik seçmeniz gerekir. Bu sadece yüksek performans sağlayan gözlemle seçilen bir sayı olabilir. Ayrıca yüksek skorlu hatların sayısını da hesaba katabilir.

Eğitimi

Eğitmek için, dilde büyük, temsili bir kod örneği sağlayın. Kod metni üzerinde döngü yapmak için bir program yazın ve dosyadaki her bir N-gramını (N aralığı parametrelendirilmelidir) sonraki karakterin istatistiksel frekansıyla ilişkilendirin. Bu, her biri bir olasılıkla ilişkili olan bigramı takip eden birden fazla olası karakter durumu verecektir. Örneğin, "()" bigramının aşağıdaki karakter olasılıkları olabilir:

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

Birincisi, örneğin "Noktalı virgülün boş bir parantez izlemesi olasılığı 0,5" şeklinde okunmalıdır.

Eğitim için, iki ila beş büyüklüğünde N-gram tavsiye ederim. Bu konuda biraz araştırma yaptığımda , N-gram büyüklüğünün iki ila beş arasında İngilizce için iyi çalıştığını gördük. Kaynak kodun çoğu İngilizce gibi olduğundan, bu aralıktan başlayıp neyin işe yaradığını bulduğunuzda en uygun parametre değerlerini bulmak için ayarlama yapmanızı öneririm.

Bir uyarı: Model, tanımlayıcılardan, yöntem adlarından, boşluktan vb. Etkilenecektir. Ancak, eğitim örneğinin belirli özelliklerini atlamak için eğitimi ayarlayabilirsiniz. Örneğin, gereksiz tüm boşlukları daraltabilirsiniz. Girişteki boşluk alanının (Yığın Taşması direği) varlığı da göz ardı edilebilir. Ayrıca, değişken tanımlayıcı adlandırma kuralları karşısında daha esnek olacak alfabetik durumu da göz ardı edebilirsiniz.

araştırmam sırasında, yöntemlerimizin İspanyolca'nın yanı sıra İngilizce için de iyi çalıştığını gördük. Bunun neden kaynak kodu için de işe yaramayacağını anlamıyorum. Kaynak kodu insan dilinden daha yapılandırılmış ve öngörülebilir.

23
Matthew Rodatus

Radikal olarak farklı bir yaklaşım önerebilir miyim? SO izin verilen tek insan dili İngilizce'dir, bu yüzden İngilizce olmayan her şeyin kod snippet olma şansının% 99,9'u vardır.

Benim çözümüm şu olurdu: orada birçok İngilizce dil denetleyicisinden birini kullanın (sadece yanlış yazımların yanı sıra - çift nokta gibi sözdizimi hatalarını veya # veya ~). Sonra büyük miktarda hata ve uyarı atan satır/paragraf "bu kod mu?" soru.

Bu yaklaşım elbette İngilizce dışındaki dilleri kullanan StackExchange siteleri için de uyarlanabilir.

Sadece benim 2 ¢ ...

13
mac

Sahte kod gerçek bir zorluk oluşturabilir çünkü tüm programlama dilleri '[]', ';', '()' vb. Gibi özel karakterlere bağlıdır. Bu özel karakterlerin oluşumunu saymanız yeterlidir. Tıpkı bir ikili dosya algılayacağınız gibi (örneğin% 5'inden fazlası bayt değeri 0 içerir).

11
Ivo Limmen

Muhtemelen bunun için birkaç aşağı oy alacağım ama sanırım buna yanlış açıdan yaklaşıyorsunuz.

Bu hat beni yakaladı:

insanlar içeri girmeli ve bunu bir şekilde anlayamayan insanlar için kodu manuel olarak biçimlendirmelidir

Bu bakış açısı IMO biraz kibirli. Programcıların ve tasarımcıların, problemin kullanıcı değil, yazılımın kendisi veya en azından kullanıcı arayüzü olmadığında, yazılımı nasıl doğru kullanacağını anlayamayan kullanıcılarla rahatsız olduğu yazılım tasarımında çok şey buluyorum.

Bu sorunun asıl nedeni kullanıcı değil, bunu yapabildikleri açık değildir.

Bunu daha açık hale getirmek için kullanıcı arayüzündeki bir değişikliğe ne dersiniz? Elbette bu olacak:

  1. yeni kullanıcılara tam olarak yapmaları gerekeni daha açık
  2. çok dilde kod mantığını algılamak için karmaşık algoritmalar yazmak yerine daha kolay

Misal:

enter image description here

11
matt_asbury

Bunu sadece belirli dillere karşı hedeflemeniz gerekebileceğini düşünüyorum, genel olarak bu sorun İngilizce'ye oldukça benzeyen diller alabileceğiniz için muhtemelen zor olabilir (örn. inform7 ). ama neyse ki en çok kullanılanlar oldukça kolay bir şekilde kapatılabilir.

İlk kesimim C; C++, Java, C # ve benzer sözdizimini kullanan ve gerçekten basit olan diğer diller için iyi bir eşleşme sağlayacak ";\n" dizisini aramak olacaktır. Ayrıca İngilizce olarak kullanılması daha az olasıdır; yeni satır olmadan

4
jk.

Birisi etiketlere baktıktan sonra bunun için sözdizimi aradığından bahsetti, ancak bu yeni kullanıcılara yönelik olduğu için düşürüldü.

Olası daha iyi bir çözüm, sorunun gövdesinde dil adlarını aramak, ardından aynı stratejiyi uygulamak olacaktır. "Javascript", "Java" veya "C #" dan bahsedersem, sorunun nedeni budur ve sorudaki kodun o dilde olması muhtemeldir.

4
Omar Kooheji

İlk olarak, yazım denetimi ile çalıştırın, çok az uygun İngilizce kelime bulacaktır, ancak yazım denetimcisinin bölmeyi önereceği birçok kelime olmalıdır.

Sonra, düz İngilizce için tipik olmayan, kod için tipik olan noktalama işaretleri/özel karakterler vardır:

  • something(); sadece düz İngilizce olamaz;
  • $something burada something sayısal değildir;
  • -> boşlukları olmayan kelimeler arasında;
  • . boşluk olmayan kelimeler arasında;

Elbette iyi çalışmasını sağlamak için, Bayesian sınıflandırıcısının bu özelliklerin üzerine inşa edilmesini isteyebilirsiniz.

1
vartec

benzer sözdizimini paylaşan birkaç dil kümesi vardır. çoğu dil birkaç dilden etkilendi, bu yüzden diller [AMPL, AWK, csh, C++, C--, C #, Objective-C, BitC, D, Go, Java, JavaScript, Limbo, LPC, Perl, PHP, Pike, Processing [hepsi C'den etkilendi, bu yüzden C'yi tespit ederseniz muhtemelen tüm bu dilleri tespit edersiniz. bu yüzden sadece bu dil setlerini tespit etmek için basit bir desen yazmalısınız.

ayrıca en blok iki yeni satır veya benzer yazıdaki diğer metin blokları ile bölünecek çünkü metin bloklar halinde bölmek olacaktır.

javascript (c ailesi için çok basit olmayan bir örnek) ile bu kolayca yapılabilir:

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

Geleceğin en kanıtı olabilecek ve uzun vadede en az manuel ayarlamayı gerektiren şey, çünkü diğer diller (şu anda en çok kullanılan programlama dillerinden biraz farklı görünüyor) daha popüler hale geliyor ve şu anda kullanılan diller daha az popüler hale geliyor, ab ve a () vb. gibi belirli şeyleri aramak yerine Google Çeviri yapar ("Nasıl çalışır?" başlıklı paragrafa bakın).

Başka bir deyişle, aramak için kodda bulunan kalıpları manuel olarak düşünmek yerine, bilgisayar kendi başına çözebilir . Bu,

  1. birçok farklı programlama dilinde birçok kod

    • Öneri: Google Code veya Github gibi web tabanlı kaynak kodu havuzlarından veya hatta Stackoverflow'daki zaten kod olarak işaretlenmiş şeylerden kod örneklerini otomatik olarak alın

    • Not: kod yorumlarını ayrıştırmak iyi bir fikir olabilir

  2. web'deki makalelerden alınan birçok İngilizce metin

    • programlama ile ilgili makalelerden olmasa da (aksi takdirde kodları olabilir ve sistemi karıştırabilir :-))

ve bir tür algoritmaya sahip olmak otomatik olarak kodda ingilizce olmayan ve tam tersi olan kalıpları bulun ve algoritmayı çalıştırarak kodun ne olduğunu ve kod olmayanları tespit etmek için bu kalıpları kullanın gönderilerde.

(Ancak, böyle bir algoritmanın nasıl çalışacağından emin değilim. Mevcut soruya verilen diğer yanıtlar bunun için yararlı bilgilere sahip olabilir.)

Daha sonra sistem, kodun o noktaya bakış biçimindeki değişiklikleri hesaba katmak için kodu arada bir yeniden tarayabilir.

0
Abbafei

Her satır için kelimeleri/noktalama karakterini saymanız yeterlidir. İngilizce 4 veya daha fazla, 2'den daha az kodlu olma eğilimindedir.

Yukarıdaki paragrafta örneğin 18 kelime ve 4 noktalama karakteri vardır. Bu paragrafın 19 kelimesi ve 4 noktalaması vardır, bu nedenle beklentiler dahilindedir.

Tabii ki, bu yeni başlayanlar ingilizce zayıf konuşmacıların sorularına karşı test edilmelidir ve bu durumlarda istatistiklerin çarpık olması olabilir.

Ben [boşluk olmayan]. [Boşluk veya satırsonu] kod çok nadir, ancak İngilizce yaygın olduğunu, bu yüzden bu noktalama işareti değil, kelime olarak sayılabilir.

Bence en büyük sorun inline kodu olacak, nerede biri gibi bir soru soruyor:

(İ = 0; i> 100; i ++) {} için söylersem bu ne anlama geliyor?

Bu kod ve İngilizce'dir ve geri keneler gibi işaretlenmelidir:

for (i=0; i>100; i++) {} dersem bu ne anlama geliyor?

0
rjmunro

Ben ilk önce sadece bu şekilde tanımlanması gereken (yeterince) biçimlendirilmiş kod ve yine de manuel biçimlendirme gerektiren (çok) kötü biçimlendirilmiş kod arasında bir ayrım yapmak gerektiğini düşünüyorum.

Biçimlendirilmiş kodda kesme çizgileri ve girinti var. Yani: eğer bir satırdan önce tek bir kesme çizgisi gelirse, iyi bir adayınız olur. Bunun üzerinde önde gelen boşluklar varsa, çok iyi bir adayınız var.

Normal metin iki kesme çizgisi veya iki boşluk ve biçimlendirme için bir kesme çizgisi kullanır, bu nedenle ayrım için açık bir kriter vardır.

LISP kodunda noktalı virgül bulamazsınız, Ruby kodunda parantez bulamayabilirsiniz, sözde kodda çok fazla bulamayabilirsiniz.Ancak herhangi bir (ezoterik olmayan) dilde bulacaksınız kesme çizgileri ve girintilerle biçimlendirilecek iyi bir kod Bu kadar evrensel bir şey yok çünkü son kodda insanlar tarafından okunacak şekilde yazılmıştır.

İlk olarak potansiyel kod satırlarını kod arayın. Ayrıca, kod satırları genellikle gruplar halinde gelir. Eğer bir tane varsa, yukarı veya aşağıdakinin de bir kod satırı olması iyi bir şanstır.

Potansiyel kod satırlarını seçtikten sonra ölçülebilir ölçütlere göre kontrol edin ve bir eşik seçin:

  • word dışı karakterlerin sıklığı
  • tanımlayıcıların sıklığı: CamelCase veya under_score stili ile çok kısa veya çok uzun kelimeler
  • yaygın olmayan kelimelerin tekrarı

Ayrıca, şimdi programcılar ve cs olduğuna göre, stackoverflow'un kapsamı açıkça daraltılmıştır. Tüm dil etiketlerini dil olarak göstermeyi düşünebilirsiniz. Gönderirken en az bir dil etiketi seçmeniz, language-agnostic etiketi veya açıkça atlamak için.

İlk durumda hangi dillerin aranacağını biliyorsunuz, ikinci durumda sahte kod aramak isteyebilirsiniz ve son durumda muhtemelen herhangi bir kod olmayacaktır, çünkü bu bazı teknolojilerle ilgili bir soru veya çerçeve veya benzeri.

0
back2dos

Tespit etmek istediğiniz her dil için bir ayrıştırıcı oluşturabilirsiniz (ANTLR için dil tanımlarının bulunması genellikle kolaydır), ardından sorunun her satırını her ayrıştırıcı aracılığıyla çalıştırabilirsiniz. Herhangi bir satır doğru ayrışırsa, muhtemelen kodunuz vardır.

Buradaki sorun, bazı İngilizce (doğal dil) cümlelerinin kod olarak ayrıştırılabilmesidir, bu nedenle diğer fikirlerin bazılarını da dahil etmek isteyebilirsiniz veya yalnızca bir veya iki ardışık satırdan fazlası doğru şekilde ayrıştırılırsa olumlu sonuçları sınırlayabilirsiniz. aynı dil ayrıştırıcısı.

Diğer potansiyel sorun, bunun muhtemelen sahte kodu almamasıdır, ancak bu iyi olabilir.

0
Jeff Knecht