2009-08-21 31 views
6

Làm cách nào để mô phỏng từ khóa SQL LIKE trong JavaScript?Thi đua SQL LIKE trong JavaScript

Đối với những người bạn của những người không biết LIKE là gì, đó là một regex rất đơn giản mà chỉ hỗ trợ các ký tự đại diện %, mà phù hợp với 0 hoặc nhiều ký tự, và _ mà phù hợp chính xác một ký tự.

Tuy nhiên, nó không chỉ có thể làm một cái gì đó như:

var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null; 

... bởi vì mô hình có thể chứa dấu chấm, các ngôi sao và bất kỳ ký tự regex đặc biệt khác.

+0

fyi- trong mã mẫu của bạn, bạn đang bỏ lỡ một ngoặc gần trước khi " '.exec'" – Kip

+0

@ C.ba rlow: đừng ngần ngại xóa các dấu hiệu cũ hơn 'chỉnh sửa: .. blah' khi chỉnh sửa.Nhằm mục đích "câu hỏi độc lập tốt nhất"; lịch sử chỉnh sửa ở đó cho tất cả mọi người xem, vì vậy không cần phải giữ bình luận xung quanh. :) – sarnold

+0

@sarnold Gotcha! Cảm ơn bạn đã hướng dẫn! –

Trả lời

6

Những gì bạn có sẽ làm việc miễn là bạn đầu tiên thoát khỏi nhân vật regex trong mô hình của bạn. Dưới đây là một ví dụ từ Simon Willison’s blog:

RegExp.escape = function(text) { 
    if (!arguments.callee.sRE) { 
    var specials = [ 
     '/', '.', '*', '+', '?', '|', 
     '(', ')', '[', ']', '{', '}', '\\' 
    ]; 
    arguments.callee.sRE = new RegExp(
     '(\\' + specials.join('|\\') + ')', 'g' 
    ); 
    } 
    return text.replace(arguments.callee.sRE, '\\$1'); 
} 

Sau đó, bạn có thể thực hiện mã của bạn như:

likeExpr = RegExp.escape(likeExpr); 
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null; 
+1

Giả sử những gì bạn đã có - 'RegExp.like = function (văn bản) {return new RegExp ("^"+ (RegExp.escape (văn bản) .replace (/%/g,". * ") .thay thế (/ _/g, ".")) + "$"); } 'có thể tái sử dụng nhiều hơn một chút cho anh ta. – gnarf

+0

Việc triển khai thực hiện 'Regex.escape' đó khá là quá mức. Trước hết, 'arguments.callee' xảy ra ngăn một số tối ưu hóa trong các trình duyệt hiện đại (và không được chấp nhận trong ES5-strict), vì vậy tốt hơn nên tránh nó khi có thể. Thứ hai, có một ký tự thoát không cần thiết của ký tự, khi thay vào đó chúng có thể được đặt trong một lớp nhân vật. Đây là phiên bản nhỏ hơn (và có khả năng nhanh hơn) mà chúng tôi sử dụng trong Prototype.js - 'RegExp.escape = function (str) {return str.replace (/ ([. * +?^=!: $ {} () | [\] \/\\])/g, '\\ $ 1'); }; ' – kangax

1

Nếu bạn muốn sử dụng regex, bạn có thể bọc từng ký tự của chuỗi trong dấu ngoặc vuông. Sau đó, bạn chỉ có một vài nhân vật để trốn thoát.

Nhưng một lựa chọn tốt hơn có thể là để cắt ngắn chuỗi mục tiêu nên chiều dài phù hợp với chuỗi tìm kiếm của bạn và kiểm tra xem có sự bình đẳng.

2

Dưới đây là một chức năng tôi sử dụng, dựa trên PHP's preg_quote function:

function regex_quote(str) { 
    return str.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1"); 
} 

Vì vậy, dòng của bạn sẽ bây giờ là:

var match = new RegEx(regex_quote(likeExpr).replace("%", ".*").replace("_", ".")).exec(str) != null; 
3

tôi đang tìm kiếm một câu trả lời cùng một câu hỏi và đến với điều này sau khi đọc bài trả lời Kip của:

String.prototype.like = function(search) { 
    if (typeof search !== 'string' || this === null) {return false; } 
    // Remove special chars 
    search = search.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1"); 
    // Replace % and _ with equivalent regex 
    search = search.replace(/%/g, '.*').replace(/_/g, '.'); 
    // Check matches 
    return RegExp('^' + search + '$', 'gi').test(this); 
} 

Sau đó bạn có thể sử dụng nó như sau (lưu ý rằng nó bỏ qua chữ hoa/thường):

var url = 'http://www.mydomain.com/page1.aspx'; 
console.log(url.like('%mydomain.com/page_.asp%')); // true 

LƯU Ý 29/11/2013: Cập nhật với RegExp.test() cải thiện hiệu suất theo nhận xét của Lucios bên dưới.

+0

thay vì !! this.match (..., bạn không nên sử dụng phương thức này.test (...? –

+0

hi @ LucioM.Tato, x.test() dành cho các trường hợp RegExp, không phải cho Chuỗi đối tượng .. [http://www.w3schools.com/jsref/jsref_regexp_test.asp](http://www.w3schools.com/jsref/jsref_regexp_test.asp) –

+0

Tôi xin lỗi tôi không rõ ràng. tái nhận được một mảng phù hợp (regexp đắt tiền) thay vì sử dụng .test (hiệu suất tốt hơn) .Để được: trả lại mới RegExp (...) .kiểm tra (this), thay vì chuyển đổi một mảng hoặc null thành boolean bằng double negation .. http://stackoverflow.com/questions/10940137/regex-test-vs-string-match-to-know-if-a-string-matches-a-regular-expression –

0

Trong câu trả lời Chris Van Opstal của bạn nên sử dụng replaceAll thay vì thay thế để thay thế tất cả occurrances của '%' và '_'. Tham khảo cách làm replaceAll - here

0

Johnny đến thời gian gần đây ở đây nhưng công trình này cho tôi, tôi sử dụng nó cho các trang spa của tôi để tránh các trang nhất định hiển thị kết quả sau khi trang mặc định:

function like(haystack,needle){ 
    needle = needle.split(','); 
    var str = haystack.toLowerCase(); 
    var n = -1; 
    for(var i=0;i<needle.length;i++){ 
     n = str.search(needle[i]); 
     if(n > -1){ 
      return n; 
     } 
    } 
return n; 
} 

sử dụng là - ở đây tôi muốn không hiển thị bất kỳ kết quả trên các công cụ, tiếp xúc hoặc nhà trang - kết quả() là một hàm tôi không hiển thị ở đây:

var n = like($data,'tools,contact,home'); 
//~ alert(n); 
if(n < 0){// does not match anything in the above string 
    results($data); 
}