Phương pháp đơn giản để phát hiện mã đáng tin cậy trong văn bản?


142

GMail có tính năng này, nơi nó sẽ cảnh báo bạn nếu bạn cố gửi một email mà nó nghĩ có thể có tệp đính kèm.

Ý của bạn là đính kèm tập tin?

Vì GMail đã phát hiện chuỗi see the attachedtrong email, nhưng không có tệp đính kèm thực tế, nó cảnh báo tôi bằng hộp thoại OK / Hủy khi tôi nhấp vào nút Gửi.

Chúng tôi có một vấn đề liên quan đến Stack Overflow. Đó là, khi người dùng vào một bài đăng như thế này :

vấn đề của tôi là tôi cần thay đổi cơ sở dữ liệu nhưng tôi sẽ không tạo 
một kết nối mới. thí dụ:

Bộ dữ liệu dsMasterInfo = new Dataset ();
Cơ sở dữ liệu db = DatabaseFactory.CreateDatabase ("ConnectionString");
DbCommand dbCommand = db.GetStoredProcCommand ("uspGetMasterName");

Người dùng này không định dạng mã của họ là mã!

Đó là, họ không thụt lề bởi 4 dấu cách trên Markdown hoặc sử dụng nút mã (hoặc phím tắt ctrl+ k) để thực hiện điều đó cho họ.

Do đó, hệ thống của chúng tôi đang chấp nhận rất nhiều chỉnh sửa mà mọi người phải vào và định dạng mã theo cách thủ công cho những người mà bằng cách nào đó không thể tìm ra điều này. Điều này dẫn đến rất nhiều đau bụng . Chúng tôi đã cải thiện trình chỉnh sửa nhiều lần, nhưng không lái xe tới nhà người dùng và nhấn các nút chính xác trên bàn phím cho họ, chúng tôi không biết phải làm gì tiếp theo.

Đó là lý do tại sao chúng tôi đang xem xét cảnh báo kiểu Google Gmail:

Ý của bạn là đăng mã?

Bạn đã viết những thứ mà chúng tôi nghĩ giống như mã, nhưng bạn đã không định dạng nó dưới dạng mã bằng cách thụt vào 4 khoảng trắng, sử dụng nút mã thanh công cụ hoặc lệnh định dạng mã ctrl+ k.

Tuy nhiên, việc trình bày cảnh báo này yêu cầu chúng tôi phát hiện sự hiện diện của những gì chúng tôi nghĩ là mã không được định dạng trong một câu hỏi . Một cách đơn giản, bán đáng tin cậy để làm điều này là gì?

  • Mỗi Markdown , mã luôn được thụt vào 4 chỗ hoặc trong vòng backticks, vì vậy bất cứ điều gì đúng định dạng có thể được loại bỏ từ việc kiểm tra ngay lập tức.
  • Đây chỉ là một cảnh báo và nó sẽ chỉ áp dụng cho những người dùng có uy tín thấp hỏi những câu hỏi đầu tiên của họ (hoặc cung cấp câu trả lời đầu tiên của họ), vì vậy một số thông tin sai là ổn, miễn là khoảng 5% hoặc ít hơn.
  • Các câu hỏi về Stack Overflow có thể bằng bất kỳ ngôn ngữ nào , mặc dù chúng tôi thực sự có thể giới hạn kiểm tra của chúng tôi đối với các ngôn ngữ "mười lớn". Trên mỗi trang thẻ sẽ là C #, Java, PHP, JavaScript, Objective-C, C, C ++, Python, Ruby.
  • Sử dụng kết xuất dữ liệu commons của Stack Overflow để kiểm tra giải pháp tiềm năng của bạn (hoặc chỉ chọn một vài câu hỏi trong 10 thẻ hàng đầu trên Stack Overflow) và xem cách thực hiện.
  • Mã giả là tốt, nhưng chúng tôi sử dụng c # nếu bạn muốn thân thiện hơn.
  • Càng đơn giản càng tốt (miễn là nó hoạt động). HÔN! Nếu giải pháp của bạn yêu cầu chúng tôi cố gắng biên dịch các bài đăng trong 10 trình biên dịch khác nhau hoặc một đội quân người để tự đào tạo một công cụ suy luận bayes, thì đó ... không chính xác như những gì chúng tôi đã nghĩ.

34
Tôi nghĩ rằng nếu bạn luôn luôn hiển thị cảnh báo nếu không có hiện tượng thụt đầu dòng, bạn sẽ ở dưới mức giới hạn lỗi 5%. Đây chỉ là một nửa có nghĩa là một trò đùa.
Konrad Rudolph

59
@Konrad Điều này sẽ hoạt động tốt hơn nữa nếu thông báo sẽ là: 'Hoặc câu hỏi của bạn bị thiếu mẫu mã sẽ giúp người khác hiểu nó hoặc bạn quên thụt lề đúng cách'. Điều này sẽ bao gồm 99% của tất cả các trường hợp.
thorsten müller

3
Đây là một câu hỏi TỐT nhưng tôi cảm thấy nó không có câu trả lời. Bạn chỉ cho tôi một hệ thống chống ngớ ngẩn và tôi sẽ cho bạn thấy một thằng ngốc tốt hơn. Ngay cả khi vấn đề này có thể được giải quyết bằng CODE, có lẽ nó không nên? Chính những người thiếu hiểu biết này không thể bị làm phiền khi hỏi CÂU HỎI SỞ HỮU đang làm hỏng trang web này cho những người như tôi, những người đặt câu hỏi thích hợp và đóng góp câu trả lời thích hợp IMHO.
maple_shaft

2
Một mẫu phổ biến mà tôi đã thấy là một khối mã được thụt lề chính xác, nhưng trong đó các dòng đầu tiên và cuối cùng (thường chỉ có hai dòng đó, đôi khi nhiều hơn khi hiển thị nhiều chức năng, chẳng hạn) không được gắn nhãn là mã. Điều này có lẽ nên được phát hiện quá.
3Doubloons

3
Bên cạnh đó, văn bản xác nhận GMail khá khó hiểu. Nếu câu trả lời của bạn cho câu hỏi đầu tiên là 'có' thì câu trả lời cho câu hỏi thứ hai là 'không' ...
pimvdb

Câu trả lời:


147

Một giải pháp thích hợp có thể là một số mô hình đã học / thống kê, nhưng đây là một số ý tưởng thú vị:

  1. Bán dấu hai chấm ở cuối dòng . Điều này một mình sẽ bắt được một loạt các ngôn ngữ.
  2. Dấu ngoặc trực tiếp theo văn bản không có khoảng trắng để phân tách nó: myFunc()
  3. Một dấu chấm hoặc mũi tên giữa hai từ: foo.bar = ptr->val
  4. Sự hiện diện của dấu ngoặc nhọn, dấu ngoặc: while (true) { bar[i]; }
  5. Sự hiện diện của cú pháp "bình luận" (/ *, //, v.v.): /* multi-line comment */
  6. Các ký tự / toán tử không phổ biến: +, *, &, &&, |, ||, <, >, ==, !=, >=, <=, >>, <<, ::, __
  7. Chạy cú pháp tô sáng của bạn trên văn bản. Nếu nó kết thúc làm nổi bật một số phần trăm cao của nó, nó có thể là mã.
  8. văn bản camelCase trong bài.
  9. dấu ngoặc đơn, dấu ngoặc nhọn và / hoặc dấu ngoặc.

Người ta có thể theo dõi số lần mỗi lần xuất hiện và những lần này có thể được sử dụng làm các tính năng trong thuật toán học máy như perceptron , như cách SpamAssassin thực hiện.


25
Mẹo: 3 có trọng lượng rất thấp, vì một dấu chấm giữa các từ có thể là kết quả của một lỗi đánh máy. 5 không nên phù hợp với URL. Đối với 6 ký hiệu và cũng thường được sử dụng bên ngoài bối cảnh mã, bạn cũng có thể giảm trọng lượng ký tự đó. Kiểm tra kỹ nếu công cụ tô sáng hoạt động, bởi vì nó có thể làm nổi bật văn bản không mã như tôi đôi khi thấy trong Notepad ++.
Tamara Wijsman

8
lại như một lỗi đánh máy - sẽ không có hại gì khi gắn cờ mà tác giả phải chỉnh sửa bằng mọi cách.
dùng151019

4
ngoài ra, các từ khóa cụ thể mà nhiều ngôn ngữ có thể giúp: WHILE, ELSE, IF, LOOP, BREAK, v.v.
JoséNunoFerreira

6
Thêm "Cách sử dụng $ trước các từ không số: $ var là phổ biến trong Perl và PHP (và Ruby?)."
PhiLho

4
Bạn sẽ không phát hiện ra tôi SELECT DISTINCT name FROM people WHERE id IS NOT NULL.
Benoit

54

Tôi sẽ tò mò muốn xem các số liệu trung bình của tiếng Anh viết ở một bên và mã ở bên kia là gì.

  • độ dài của đoạn văn
  • chiều dài của dòng
  • kích thước của từ
  • ký tự được sử dụng
  • tỷ lệ giữa các ký tự chữ cái, số và ký tự khác
  • số ký hiệu trên mỗi từ
  • Vân vân.

Có lẽ điều đó một mình có thể phân biệt giữa mã và phần còn lại. Ít nhất tôi tin rằng mã, bất kể ngôn ngữ, sẽ hiển thị một số số liệu khác nhau đáng chú ý trong nhiều trường hợp.

Tin tốt là: bạn đã có nhiều dữ liệu để xây dựng số liệu thống kê của mình.


Ok tôi trở lại với một số dữ liệu để ủng hộ các giả định của mình. :-)

Tôi đã thực hiện một bài kiểm tra nhanh và bẩn trên bài đăng của riêng bạn và trên bài đăng đầu tiên tôi tìm thấy trên StackOverflow , với một công cụ khá tiên tiến : wc.

Đây là những gì tôi đã có sau khi chạy wctrên phần văn bản và phần mã của hai ví dụ sau:

Đầu tiên chúng ta hãy xem phần tiếng Anh :

  • Phần tiếng Anh trong bài đăng của bạn (2635 ký tự, 468 từ, 32 dòng)
    • 5 ký tự / từ, 82 ký tự / dòng, 14 từ / dòng
  • Phần tiếng Anh của bài khác (1499 ký tự, 237 từ, 12 dòng)
    • 6 ký tự / từ, 124 ký tự / dòng, 19 từ / dòng

Khá giống bạn không nghĩ sao?

Bây giờ hãy xem phần mã !

  • Phần mã của bài đăng của bạn (174 ký tự, 13 từ, 3 dòng)
    • 13 ký tự / từ, 58 ký tự / dòng, 4 từ / dòng
  • Phần mã của bài đăng khác (4181 ký tự, 287 từ, 151 dòng)
    • 14 ký tự / từ, 27 ký tự / dòng, 2 từ / dòng

Xem các số liệu đó không khác nhau như thế nào, nhưng quan trọng hơn, chúng khác với các số liệu tiếng Anh như thế nào? Và đây chỉ là sử dụng một công cụ hạn chế. Bây giờ tôi chắc chắn rằng bạn có thể nhận được một cái gì đó thực sự chính xác bằng cách đo nhiều số liệu hơn (tôi đang nghĩ cụ thể là số liệu thống kê ký tự).

Tôi có thể haz cookie?


6
Độ dài của dòng, đặc biệt nếu bạn loại trừ các dấu đầu dòng và tìm các dòng có độ dài nhỏ hơn một độ dài cụ thể có chứa dấu chấm cụ thể có vẻ là một biện pháp tốt.
Jon Hopkins

Điều này sẽ làm việc cho các khối mã, nhưng có vẻ khó hơn rất nhiều để tìm kiếm cdde nội tuyến. Tuy nhiên, không chắc chắn vấn đề đó quan trọng đến mức nào - vấn đề lớn hơn là các khối lớn của mã không được định dạng.
cHao

3
Không có bánh quy. Liên kết trong bài đăng của bạn là 404.
james.garriss

@ james.garriss: Internet đã đánh cắp lọ cookie của tôi. :( Cảm ơn bạn đã thông báo mặc dù.
Julien Guertault

23

Thông thường, chuỗi Markov được sử dụng để tạo văn bản, nhưng chúng cũng có thể được sử dụng để dự đoán sự giống nhau của văn bản (theo CE Shannon 1950 ) với một mô hình được đào tạo. Tôi đề nghị nhiều chuỗi Markov.

Đối với mỗi ngôn ngữ phổ biến, đào tạo chuỗi Markov trên một mẫu mã lớn, đại diện trong ngôn ngữ. Sau đó, đối với bài đăng Stack Overflow mà bạn muốn phát hiện mã, hãy thực hiện các thao tác sau cho từng chuỗi:

  • Vòng qua các dòng trong bài.
    • Khai báo hai biến: ACTUAL = 1.0 và HIGHEST = 1.0
    • Lặp lại qua từng ký tự trong dòng.
      • Đối với mỗi ký tự, tìm xác suất trong chuỗi Markov rằng ký tự hiện tại là ký tự theo sau N ký tự trước đó. Đặt THỰC TẾ = THỰC TẾ * VẤN ĐỀ 1 . Nếu ký tự hiện tại không có trong chuỗi, thì hãy sử dụng một giá trị nhỏ cho PROB 1 , như 0,000001.
      • Bây giờ, tìm ký tự có khả năng nhất (nghĩa là xác suất cao nhất) để theo dõi các ký tự N trước đó. Đặt CAO NHẤT = CAO NHẤT * VẤN ĐỀ 2 .
      • Rõ ràng, PROB 2 > = PROB 1

Đối với mỗi dòng, bạn nên có một giá trị THỰC TẾ và CAO NHẤT. Chia THỰC TẾ cho CAO NHẤT. Điều đó sẽ cung cấp cho bạn điểm thể lực về việc một dòng cụ thể có phải là mã nguồn hay không. Điều đó sẽ liên kết một số với mỗi dòng trong ví dụ bạn đã đưa ra:

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

Cuối cùng, bạn sẽ cần chọn một ngưỡng để xác định khi nào có mã trong bài. Đây có thể chỉ đơn giản là một số được lựa chọn bằng cách quan sát mang lại hiệu suất cao. Nó cũng có thể tính đến số lượng dòng với số điểm cao.

Đào tạo

Để đào tạo, mua một mẫu mã lớn, đại diện bằng ngôn ngữ. Viết chương trình lặp qua văn bản mã và liên kết từng N-gram trong tệp (phạm vi cho N nên được tham số hóa) với tần số thống kê của ký tự tiếp theo. Điều này sẽ mang lại nhiều trạng thái có thể có của các ký tự theo bigram, mỗi trạng thái được liên kết với một xác suất. Ví dụ: bigram "()" có thể có một số xác suất ký tự sau:

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

Đầu tiên nên được đọc, ví dụ như "Xác suất một dấu chấm phẩy theo sau một ngoặc đơn trống là 0,5."

Đối với đào tạo, tôi đề nghị N-gram có kích thước từ hai đến năm. Quay lại khi tôi thực hiện một số nghiên cứu về điều này , chúng tôi thấy rằng N-gram cỡ hai đến năm hoạt động tốt cho tiếng Anh. Vì phần lớn mã nguồn là tiếng Anh, nên tôi khuyên bạn nên bắt đầu với phạm vi đó và sau đó điều chỉnh để tìm các giá trị tham số tối ưu khi bạn tìm thấy những gì hoạt động.

Thông báo trước: Mô hình sẽ bị ảnh hưởng bởi các định danh, tên phương thức, khoảng trắng, v.v. Tuy nhiên, bạn có thể điều chỉnh đào tạo để bỏ qua các tính năng nhất định của mẫu đào tạo. Ví dụ, bạn có thể thu gọn tất cả các khoảng trắng không cần thiết. Sự hiện diện của khoảng trắng trong đầu vào (bài viết Stack Overflow) cũng có thể bị bỏ qua. Bạn cũng có thể bỏ qua trường hợp theo thứ tự chữ cái, sẽ dễ phục hồi hơn khi đối mặt với các quy ước đặt tên định danh khác nhau.

Trong quá trình nghiên cứu của tôi , chúng tôi thấy rằng các phương pháp của chúng tôi hoạt động tốt cho tiếng Tây Ban Nha cũng như tiếng Anh. Tôi không thấy lý do tại sao điều này cũng sẽ không hoạt động tốt cho mã nguồn. Mã nguồn thậm chí còn có cấu trúc và dự đoán hơn ngôn ngữ của con người.


2
Vấn đề duy nhất tôi thấy trước là xác suất sẽ nhỏ hơn rất nhiều so với ví dụ về đồ chơi của bạn. Với sự không ổn định về số, điều này có nghĩa là tất cả các xác suất sẽ sớm bằng 0. Sử dụng tỷ lệ cược log sẽ giải quyết điều này. Hơn nữa, tôi sẽ sử dụng mã thông báo lớn hơn (nghĩa là không phải ký tự mà là từ / dấu chấm câu).
Konrad Rudolph

2
@Konrad: ý tưởng ở đây không phải là kiểm tra xác suất tuyệt đối: đó là kiểm tra xác suất tương đối. Đối với mỗi dòng, văn bản của dòng đó có nhiều khả năng được tạo bởi một mô hình ngôn ngữ tiếng Anh hoặc bởi một mô hình ngôn ngữ mã.
Ken Bloom

5
Bạn có thể đào tạo mô hình này trên các bài đăng SO hiện có (đặc biệt vì bạn có thể cần tính đến cú pháp Markdown). Nếu bạn cho rằng hầu hết các bài đăng được định dạng chính xác (hoặc bạn chọn qua một số lượng lớn bài đăng, theo thứ tự hàng chục nghìn, để xóa các bài đăng không được định dạng chính xác), thì bạn cho rằng những thứ không được định dạng mã là văn bản tiếng Anh và những thứ được định dạng mã là mã, bạn có thể đào tạo từ các câu trả lời SO thực tế.
Ken Bloom

1
Hướng dẫn về cách thực hiện việc này (sử dụng LingPipe trong Java) có sẵn từ trang web của LingPipe . Vào cuối hướng dẫn, có một số bài viết về các kỹ thuật để giải quyết vấn đề này. Tôi đề nghị đọc chúng.
Ken Bloom

1
Thật thú vị khi thấy rằng giải pháp hiện đại chỉ có số phiếu rất thấp và tỷ lệ thấp hơn rất nhiều so với tất cả các giải pháp đặc biệt đó, có thể chỉ là đủ tốt nhưng phụ thuộc rất nhiều vào vỏ bọc đặc biệt và vốn dĩ dễ bị quá mức.
Konrad Rudolph

13

Tôi có thể đề nghị một cách tiếp cận hoàn toàn khác nhau? Trên SO, ngôn ngữ con người duy nhất được phép là tiếng Anh, do đó, bất cứ thứ gì không phải tiếng Anh đều có 99,9% cơ hội là một đoạn mã .

Vì vậy, giải pháp của tôi sẽ là: sử dụng một trong nhiều trình kiểm tra ngôn ngữ tiếng Anh ngoài đó (chỉ cần đảm bảo rằng chúng cũng báo hiệu - bên cạnh lỗi chính tả - lỗi cú pháp như dấu chấm kép hoặc ký hiệu không phải ngôn ngữ #hoặc ~). Sau đó, bất kỳ dòng / đoạn nào ném một số lượng lớn lỗi và cảnh báo sẽ kích hoạt "đây có phải là mã không?" câu hỏi

Cách tiếp cận này cũng có thể được điều chỉnh cho các trang web StackExchange sử dụng các ngôn ngữ khác ngoài tiếng Anh, tất nhiên.

Chỉ cần 2 ...


16
Vấn đề là rất nhiều câu hỏi đến không phải là tiếng Anh (mặc dù chúng giống với nó).
Brendan Long

3
@Brendan - Đã thêm lợi thế của đề xuất này sau đó: gạch chân (hoặc tô sáng) các lỗi trong phần có thể được dự định là tiếng Anh của bài đăng và giúp người viết viết ... bằng tiếng Anh! ;)
mac

1
Tôi là người Hà Lan và mọi thứ tôi viết đều bằng tiếng Anh, bởi ý kiến ​​không phải (tùy thuộc vào dự án). Vì vậy, tiếng Anh phải là mã sẽ không đủ. Điều đó hoặc bạn có nghĩa là tiếng Anh bị hỏng phải là mã.
Ivo Limmen

@Ivo - Nhận xét của tôi đã được nói đùa về vấn đề tiếng Anh bị hỏng! ;) Tuy nhiên tôi sẽ nói rằng với các nhận xét đề xuất của tôi bằng ngôn ngữ khác sẽ hoạt động tốt ... OTOH chặn các bình luận bằng tiếng Anh sẽ không kích hoạt "đây có phải là mã không?" câu hỏi, nhưng điều đó chỉ tốt vì mã mà bình luận đã được viết sẽ kích hoạt nó ...
mac

11

Tôi có thể sẽ nhận được một vài phiếu giảm giá cho điều này nhưng tôi nghĩ rằng bạn đang tiếp cận điều này từ góc độ sai.

Dòng này đã cho tôi:

mọi người phải truy cập và định dạng thủ công mã cho những người mà bằng cách nào đó không thể tìm ra điều này

IMO quan điểm đó là loại kiêu ngạo. Tôi thấy điều này rất nhiều trong thiết kế phần mềm nơi các lập trình viên và nhà thiết kế cảm thấy khó chịu với những người dùng không thể tìm ra cách sử dụng phần mềm đúng cách, khi vấn đề không phải là người dùng mà là chính phần mềm - hoặc ít nhất là UI.

Nguyên nhân sâu xa của vấn đề này không phải là người dùng mà thực tế là họ không thể làm được điều này.

Làm thế nào về một sự thay đổi trong UI để làm cho điều này rõ ràng hơn? Chắc chắn đây sẽ là:

  1. rõ ràng hơn với người dùng mới chính xác những gì họ cần làm
  2. bạn dễ dàng xây dựng hơn thay vì viết các thuật toán phức tạp để phát hiện logic mã của vô số ngôn ngữ

Thí dụ:

nhập mô tả hình ảnh ở đây


26
Trên thực tế IMO này thực thi các câu hỏi kém như "Tôi có một vấn đề xin vui lòng giúp tôi, mã bên dưới" - khá hiếm khi mã cần được tách ra khỏi câu hỏi. Những câu hỏi hay nhất như thế này "Tôi muốn đạt được điều này và đã viết hai dòng mã này, nhưng hiệu quả là như sau, vấn đề là gì" - có rất ít mã được xen kẽ với ngôn ngữ đơn giản.
sharptooth

4
Quan sát gốc của bạn là chính xác nhưng chẩn đoán của bạn vẫn sai: trên thực tế, Jeff đang cố gắng cải thiện giao diện người dùng thông qua phương pháp này. Hơn nữa, giao diện người dùng hiện tại đã trải qua một vài chu kỳ và trong khi tôi không nghi ngờ rằng nó có thể được cải thiện (quyết liệt), tôi nghi ngờ rằng điều này sẽ giúp chống lại những kẻ ngốc lười biếng. Không có giải pháp đề xuất của bạn. @sharptooth có bảo hiểm này.
Konrad Rudolph

2
Tôi sẽ +1 vì nghĩ ra cái hộp nhưng tôi không đồng ý với đề xuất cụ thể, vì việc đăng "mã hỗ trợ" buộc một luồng câu hỏi có thể không tự nhiên. Tôi chưa bao giờ bỏ mã ở cuối câu hỏi của tôi. Tôi hầu như luôn đăng một đoạn giới thiệu, mã mẫu, sau đó là câu hỏi thực tế. Nếu bạn chấp nhận tiền đề này rằng mã nội tuyến là điều cần thiết, thì một số loại định dạng là bắt buộc - định dạng phải được nhập bởi người dùng hoặc được hệ thống khuyến nghị. Và đó là điều chính xác mà Jeff đang hỏi về việc làm.
Nicole

1
@Konrad: Ngoài nhận xét trên của tôi và phản hồi của bạn, tôi không tin rằng Jeff đang cải thiện giao diện người dùng bằng cách đi theo con đường này, mà chỉ xử lý các triệu chứng của một vấn đề tiềm ẩn. Nếu giao diện người dùng được cải thiện để không thể mắc lỗi, thì giải pháp cảnh báo người dùng sẽ không cần thiết. Tôi không hề ảo tưởng rằng ví dụ của tôi là giải pháp cuối cùng nhưng một số suy nghĩ cần phải đi vào câu hỏi "chúng ta có đang trình bày điều này theo cách tốt nhất có thể không?".
matt_asbury

1
Câu đơn giản xin vui lòng đánh dấu mã bằng cách sử dụng {}nút xung quanh hộp văn bản có thể là đủ.
Paŭlo Ebermann

11

Mã giả sẽ đặt ra một thách thức thực sự bởi vì tất cả ngôn ngữ lập trình phụ thuộc vào các ký tự đặc biệt như '[]', ';', '()', v.v. Đơn giản chỉ cần đếm sự xuất hiện của các ký tự đặc biệt này. Giống như bạn sẽ phát hiện một tệp nhị phân (hơn 5% mẫu chứa giá trị byte 0).


Tôi sẽ cải thiện điều này nhiều như có các nhóm các ký tự đặc biệt như [] (); {} =. Mỗi dòng có hơn 2-3 nhóm này chứa là một dòng mã.
Honza

... và cũng tìm kiếm các chuỗi phổ biến trong các ngôn ngữ phổ biến nhất, ví dụ: "= Somethingord ();" đối với hầu hết các ngôn ngữ khung cong, cú pháp giống như XML như "<Something>" và "<ab: cde>" và các chuỗi phổ biến khác trong các ngôn ngữ khác. Tôi tin rằng một số loại bảng tra cứu cú pháp phổ biến sẽ là một giải pháp tốt, vì bạn có thể mở rộng nó khi bạn tìm ngôn ngữ mới để thực hiện.
Arve Systad

Bạn có lẽ nên thả mã giả. Một số người thích viết nó như một ngôn ngữ kiểu C nhưng những người khác sẽ sử dụng tiếng Anh đơn giản với thứ gì đó gần gũi hơn với VB6
James P.

4

Tôi nghĩ rằng bạn có thể cần phải nhắm mục tiêu này chỉ với các ngôn ngữ cụ thể, nói chung vấn đề này có thể khó hiểu vì bạn có thể có được các ngôn ngữ khá giống với tiếng Anh (ví dụ: information7 ). nhưng may mắn là những người được sử dụng nhiều nhất có thể được bảo hiểm khá dễ dàng.

Lần cắt đầu tiên của tôi sẽ là tìm kiếm chuỗi "; \ n" sẽ giúp bạn có một kết hợp tốt cho C, C ++, Java, C # và bất kỳ ngôn ngữ nào khác sử dụng cú pháp tương tự và thực sự đơn giản. Nó cũng ít có khả năng được sử dụng bằng tiếng Anh hơn a; không có dòng mới


cộng với có thể là sự phong phú của niềng răng xoăn; p
Marc Gravell

1
Như Jeff nói trong bài đăng của mình, có lẽ họ sẽ chỉ nhắm mục tiêu các ngôn ngữ chính. Và trong mọi trường hợp, tôi nghi ngờ rằng những người dùng mới (dành cho chức năng này) sẽ có nhiều khả năng đăng C # hoặc Javascript hơn là, nói, INTERCAL ;-)
Ben

Có nhưng điều này sẽ không hoạt động với ngôn ngữ lập trình BRAINFuck hoặc BLANK. ;-)
Ivo Limmen

4

Ai đó đã đề cập đến việc xem các thẻ và sau đó tìm kiếm cú pháp cho điều đó nhưng điều đó đã bị bắn hạ vì điều này nhằm vào người dùng mới.

Một giải pháp tốt hơn có thể là tìm kiếm các tên ngôn ngữ trong phần chính của câu hỏi, sau đó áp dụng chiến lược tương tự. Nếu tôi đề cập đến "Javascript", "Java" hoặc "C #" thì rất có thể đó là câu hỏi và về mã trong câu hỏi có thể nằm trong ngôn ngữ đó.


Đặc biệt nếu tiêu đề là một cái gì đó như "vb c # .net dot net hãy giúp tôi !!!"
NickAldwin

1

Đầu tiên, chạy nó thông qua kiểm tra chính tả, nó sẽ tìm thấy rất ít từ tiếng Anh thích hợp, tuy nhiên sẽ có rất nhiều từ mà trình kiểm tra chính tả sẽ đề xuất để phân tách.

Sau đó, có các dấu chấm câu / ký tự đặc biệt không điển hình cho tiếng Anh đơn giản, điển hình cho mã:

  • something(); chỉ không thể là tiếng Anh đơn giản;
  • $somethingtrong đó somethingkhông phải là tất cả số;
  • -> giữa các từ w / o dấu cách;
  • . giữa các từ w / o khoảng trắng;

Tất nhiên để nó hoạt động tốt, bạn có thể muốn có trình phân loại Bayes được xây dựng dựa trên các đặc điểm này.


1
Phát hiện một dòng không thụt vào có chứa (); sẽ là một lý do tốt để đề xuất tin nhắn.

Trình kiểm tra chính tả nào sẽ không bị nghẹt trước khi mã được dán?
Tim Post

Với một số tin nhắn được viết bởi các nhà văn không phải người bản xứ, người kiểm tra chính tả sẽ nghẹt thở với mọi từ khác ...
PhiLho

@Ph: những câu hỏi / câu trả lời này không được chấp nhận trên SO.
vartec

1

có một số bộ ngôn ngữ chia sẻ cú pháp tương tự. hầu hết các ngôn ngữ bị ảnh hưởng bởi một vài ngôn ngữ, vì vậy các ngôn ngữ [AMPL, AWK, csh, C ++, C--, C #, Objective-C, BitC, D, Go, Java, JavaScript, Limbo, LPC, Perl, PHP, Pike, Xử lý [đều bị ảnh hưởng bởi C, vì vậy nếu bạn phát hiện ra C, bạn có thể sẽ phát hiện tất cả các ngôn ngữ này. vì vậy bạn chỉ phải viết một mẫu đơn giản để phát hiện các bộ ngôn ngữ này.

tôi cũng sẽ chia văn bản thành các khối vì phần lớn mã sẽ được chia theo hai dòng mới hoặc tương tự từ các khối văn bản khác trong bài.

điều này có thể được thực hiện dễ dàng với javascript (một mẫu không hoàn chỉnh siêu nhỏ cho gia đình 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 + "]");
   }
}

0

Đơn giản chỉ cần đếm từ / ký tự dấu chấm câu cho mỗi dòng. Tiếng Anh sẽ có xu hướng có 4 hoặc nhiều hơn, mã ít hơn 2.

Đoạn văn trên có 18 từ và 4 ký tự dấu chấm chẳng hạn. Đoạn này có 19 từ và 4 dấu câu, vì vậy trong mong đợi.

Tất nhiên, điều này sẽ cần phải được kiểm tra đối với các câu hỏi của người mới nói tiếng Anh kém, và có thể là trong những trường hợp đó, số liệu thống kê bị sai lệch.

Tôi hy vọng rằng [không phải khoảng trắng]. [Khoảng trắng hoặc dòng mới] rất hiếm trong mã, nhưng phổ biến trong tiếng Anh, vì vậy điều này có thể được tính là từ, không phải dấu câu.

Tôi nghĩ vấn đề lớn nhất sẽ là mã nội tuyến, nơi ai đó hỏi một câu hỏi như:

Nếu tôi nói cho (i = 0; i> 100; i ++) {} thì có nghĩa là gì?

Đó là mã và tiếng Anh, và nên được đánh dấu là có dấu tích ngược:

Nếu tôi nói for (i=0; i>100; i++) {}điều đó có nghĩa là gì?


0

Tôi nghĩ rằng trước tiên bạn nên phân biệt giữa mã được định dạng (đủ) chỉ cần được chỉ định thực sự như vậy và (cũng) mã được định dạng kém, dù sao cũng cần định dạng thủ công.

Mã định dạng có điểm dừng và thụt lề. Đó là: nếu một dòng được đi trước bởi một điểm dừng duy nhất, bạn có một ứng cử viên tốt. Nếu nó có khoảng trắng hàng đầu trên đó, bạn có một ứng cử viên rất tốt.

Văn bản thông thường sử dụng hai dấu chấm hoặc hai dấu cách và dấu ngắt để định dạng, do đó, có một tiêu chí rõ ràng để phân biệt.

Trong mã LISP bạn sẽ không tìm thấy dấu chấm phẩy, trong mã Ruby bạn có thể không tìm thấy dấu ngoặc đơn, trong mã giả bạn có thể không tìm thấy nhiều. Nhưng trong bất kỳ ngôn ngữ (không bí truyền) nào, bạn sẽ tìm thấy mã đàng hoàng được định dạng bằng các dấu ngắt và thụt lề. Không có gì phổ quát như thế. Bởi vì trong mã cuối cùng, được viết bởi con người.

Vì vậy, trước tiên, tìm kiếm các dòng mã tiềm năng . Ngoài ra, các dòng mã thường đi theo nhóm. Nếu bạn có một cái, rất có thể cái bên trên hoặc bên dưới cũng là một dòng mã.

Khi bạn đã chọn ra các dòng mã tiềm năng, bạn có thể kiểm tra chúng theo các tiêu chí có thể định lượng và chọn một số ngưỡng :

  • tần suất xuất hiện của các ký tự không từ
  • tần suất nhận dạng: từ rất ngắn hoặc từ rất dài với kiểu CamelCase hoặc under_score
  • sự lặp lại của những từ không phổ biến

Ngoài ra, bây giờ có lập trình viên và cs, phạm vi của stackoverflow rõ ràng bị thu hẹp. Người ta có thể xem xét biểu thị tất cả các thẻ ngôn ngữ là ngôn ngữ. Và khi đăng bài, bạn sẽ được yêu cầu chọn ít nhất một thẻ ngôn ngữ, chọn language-agnosticthẻ hoặc bỏ qua nó một cách rõ ràng.

Trong trường hợp đầu tiên, bạn biết nên tìm ngôn ngữ nào, trong trường hợp thứ hai, bạn có thể muốn tìm mã giả và trong trường hợp cuối cùng, có lẽ sẽ không có mã nào, bởi vì đó là câu hỏi liên quan đến công nghệ nào đó hoặc khuôn khổ hoặc như vậy.


0

Bạn có thể tạo một trình phân tích cú pháp cho từng ngôn ngữ bạn muốn phát hiện (định nghĩa ngôn ngữ cho ANTLR thường dễ tìm), sau đó chạy từng dòng câu hỏi thông qua mỗi trình phân tích cú pháp. Nếu bất kỳ dòng phân tích chính xác, bạn có thể có mã.

Vấn đề với điều này là một số câu tiếng Anh (ngôn ngữ tự nhiên) có thể phân tích thành mã, vì vậy bạn có thể muốn đưa vào một số ý tưởng khác hoặc bạn chỉ có thể giới hạn kết quả tích cực nếu có nhiều hơn một hoặc hai dòng liên tiếp phân tích chính xác với trình phân tích cú pháp ngôn ngữ tương tự.

Vấn đề tiềm năng khác là điều này có thể sẽ không nhận mã giả, nhưng điều đó có thể ổn.


Thông thường mọi người có lỗi cú pháp trong mã của họ (và đang hỏi về điều này).
Paŭlo Ebermann

0

Điều gì có thể là bằng chứng trong tương lai nhất và yêu cầu điều chỉnh thủ công ít nhất trong thời gian dài, vì các ngôn ngữ khác (trông hơi khác so với ngôn ngữ lập trình được sử dụng nhiều nhất hiện nay) trở nên phổ biến hơn và các ngôn ngữ hiện đang sử dụng trở nên ít phổ biến hơn, là để làm một cái gì đó giống như những gì Google Dịch làm (xem đoạn có tiêu đề "Nó hoạt động như thế nào?"), thay vì tìm kiếm những thứ nhất định như ab và a (), v.v.

Nói cách khác, thay vì tự nghĩ ra các mẫu tìm thấy trong mã để tìm kiếm, máy tính có thể tự tìm ra nó . Điều này có thể được thực hiện bằng cách có

  1. nhiều mã trong nhiều ngôn ngữ lập trình khác nhau

    • Đề xuất: tự động lấy mẫu mã từ kho lưu trữ mã nguồn dựa trên web như Google Code hoặc Github hoặc thậm chí từ những thứ trên Stackoverflow đã được đánh dấu là mã

    • Lưu ý: có thể là một ý tưởng tốt để phân tích các nhận xét mã

  2. rất nhiều văn bản tiếng Anh lấy từ các bài viết trên web

    • mặc dù không phải từ các bài viết về lập trình (nếu không họ có thể có mã trong đó và trộn hệ thống lên :-))

và có một số loại thuật toán tự động tìm các mẫu trong mã không có trong tiếng Anh và ngược lại, và sử dụng các mẫu đó để phát hiện mã nào là mã và mã nào không phải là mã bằng cách chạy thuật toán trên các bài đăng.

(Tuy nhiên, tôi không chắc một thuật toán như vậy sẽ hoạt động như thế nào. Các câu trả lời khác cho câu hỏi hiện tại có thể có thông tin hữu ích cho điều đó.)

Sau đó, hệ thống có thể quét lại mã mỗi lần một lần để tính đến những thay đổi trong cách mã nhìn vào thời điểm đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.