2008-11-11 46 views
50

tôi cần phải làm nổi bật, trường hợp insensitively, từ khóa được đưa ra trong một chuỗi JavaScript.Thay thế chuỗi không phân biệt chữ hoa chữ thường trong JavaScript?

Ví dụ:

  • highlight("foobar Foo bar FOO", "foo") nên trở "<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"

tôi cần mã để làm việc cho bất kỳ từ khóa, và do đó sử dụng một biểu thức chính quy hardcoded như /foo/i không phải là một giải pháp tối ưu.

Cách dễ nhất để thực hiện việc này là gì?

(Điều này một thể hiện của một vấn đề tổng quát hơn chi tiết trong tiêu đề, nhưng tôi cảm thấy rằng nó là tốt nhất để giải quyết vấn đề với bê tông, ví dụ hữu ích.)

Trả lời

67

Bạn thể biểu sử dụng thường xuyên nếu bạn chuẩn bị tìm kiếm chuỗi. Trong PHP, ví dụ: có một hàm preg_quote, nó sẽ thay thế tất cả các ký tự regex trong chuỗi bằng các phiên bản thoát của chúng.

Dưới đây là ví dụ một hàm cho javascript:

function preg_quote(str) { 
    // http://kevin.vanzonneveld.net 
    // + original by: booeyOH 
    // + improved by: Ates Goral (http://magnetiq.com) 
    // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 
    // + bugfixed by: Onno Marsman 
    // *  example 1: preg_quote("$40"); 
    // *  returns 1: '\$40' 
    // *  example 2: preg_quote("*RRRING* Hello?"); 
    // *  returns 2: '\*RRRING\* Hello\?' 
    // *  example 3: preg_quote("\\.+*?[^]$(){}=!<>|:"); 
    // *  returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:' 

    return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"); 
} 

(Trích từ http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_preg_quote/)

Vì vậy, bạn coudl làm như sau:

function highlight(data, search) 
{ 
    return data.replace(new RegExp("(" + preg_quote(search) + ")" , 'gi'), "<b>$1</b>"); 
} 
+0

Tôi không nghĩ rằng ví dụ của bạn hoạt động. – tvanfosson

+0

Tôi hiểu, chỉ có lần xuất hiện đầu tiên được thay thế. Không biết rằng thay thế cư xử như thế này. Các preg_quote là quan trọng nếu anh ta muốn làm nổi bật các chuỗi với/hoặc * hoặc các ký tự regex khác. – okoman

+0

Um .. it * là * javascript. Tôi chỉ nói rằng có một hàm trong PHP được gọi là preg_quote. Sau đó, tôi bao gồm một phiên bản js của chức năng đó và một chức năng js ... những ví dụ mã * là * js – okoman

0

Tại sao không chỉ cần tạo một regex mới về mỗi cuộc gọi đến chức năng của bạn? Bạn có thể sử dụng:

new Regex([pat], [flags]) 

trong đó [pat] là chuỗi cho mẫu và [flags] là cờ.

63
function highlightWords(line, word) 
{ 
    var regex = new RegExp('(' + word + ')', 'gi'); 
    return line.replace(regex, "<b>$1</b>"); 
} 
+1

Tất nhiên, bạn cần phải cẩn thận với những gì bạn đang thay thế trong và những gì bạn đang tìm kiếm trên như ghi chú @ bobince . Trên đây sẽ làm việc tốt cho văn bản đơn giản và hầu hết các tìm kiếm nếu bạn đang cẩn thận để trích dẫn các nhân vật regex của bạn ... – tvanfosson

+1

chính xác những gì tôi cần :) thx – daniellmb

+0

này sẽ chạy vào rắc rối nếu có những nhân vật regex trong từ được thay thế. @ giải pháp của okoman được xung quanh đó. –

5

Regular expressions cũng tốt miễn là từ khóa này là thực sự từ, bạn chỉ có thể sử dụng một constructor RegExp thay vì một chữ để tạo ra một từ một biến:

var re= new RegExp('('+word+')', 'gi'); 
return s.replace(re, '<b>$1</b>'); 

Khó khăn nảy sinh nếu 'từ khóa 'có thể có dấu chấm câu, vì dấu chấm câu có xu hướng có ý nghĩa đặc biệt trong regexps. Thật không may, không giống như hầu hết các ngôn ngữ/thư viện khác có hỗ trợ regexp, không có hàm chuẩn để thoát khỏi dấu chấm câu cho regexps trong JavaScript.

Và bạn không thể được hoàn toàn chắc chắn chính xác những gì nhân vật cần phải thoát vì không thực hiện của mỗi trình duyệt của regexp là đảm bảo được giống hệt nhau. (Đặc biệt, trình duyệt mới hơn có thể thêm chức năng mới.) Và xuyệc ngược-thoát nhân vật mà không phải là đặc biệt không đảm bảo vẫn làm việc, mặc dù trong thực tế nó làm.

Vì vậy, về là tốt nhất bạn có thể làm là một trong số:

  • cố gắng để nắm bắt từng ký tự đặc biệt trong việc sử dụng trình duyệt phổ biến hiện nay [Địa chỉ: thấy công thức của Sebastian]
  • xuyệc ngược-thoát khỏi tất cả các phi chữ cái và số. chăm sóc: \ W cũng sẽ khớp với các ký tự Unicode không phải ASCII mà bạn không thực sự muốn.
  • chỉ cần đảm bảo rằng không có phi chữ cái và số vào từ khóa trước khi tìm kiếm

Nếu bạn đang sử dụng này để làm nổi bật từ trong HTML mà đã có đánh dấu, rắc rối, mặc dù bạn đã có. ‘Từ’ của bạn có thể xuất hiện trong một tên phần tử hoặc giá trị thuộc tính, trong trường hợp này cố gắng quấn < b> xung quanh nó sẽ gây ra sự hỏng hóc. Trong các kịch bản phức tạp hơn có thể thậm chí là một HTML-injection vào lỗ hổng bảo mật XSS. Nếu bạn phải đối phó với đánh dấu, bạn sẽ cần một cách tiếp cận phức tạp hơn, tách ra đánh dấu '< ...>' trước khi cố xử lý từng đoạn văn bản.

13

Bạn có thể tăng cường các đối tượng RegExp với một chức năng mà không ký tự đặc biệt thoát cho bạn:

RegExp.escape = function(str) 
{ 
    var specials = /[.*+?|()\[\]{}\\$^]/g; // .*+?|()[]{}\$^ 
    return str.replace(specials, "\\$&"); 
} 

Sau đó, bạn sẽ có thể sử dụng những gì những người khác đề nghị mà không cần bất kỳ lo lắng:

function highlightWordsNoCase(line, word) 
{ 
    var regex = new RegExp("(" + RegExp.escape(word) + ")", "gi"); 
    return line.replace(regex, "<b>$1</b>"); 
} 
+0

? trong javascript RegExp cần phải được thoát với dấu gạch chéo ngược đôi như \\? – Jerinaw

+0

@Jerinaw Bạn nghĩ gì về chức năng 'RegExp.escape' của tôi? – Tomalak

+0

http://stackoverflow.com/questions/889957/escaping-question-mark-in-regex-javascript tôi đã chạy vào vấn đề mà các dấu hỏi cần thiết để được thoát với đôi \ nhưng tôi đoán trong [] bạn don' t cần phải thoát khỏi nó. – Jerinaw

4

Điều gì về một cái gì đó như thế này:

if(typeof String.prototype.highlight !== 'function') { 
    String.prototype.highlight = function(match, spanClass) { 
    var pattern = new RegExp(match, "gi"); 
    replacement = "<span class='" + spanClass + "'>$&</span>"; 

    return this.replace(pattern, replacement); 
    } 
} 

Điều này sau đó có thể được gọi là như vậy:

var result = "The Quick Brown Fox Jumped Over The Lazy Brown Dog".highlight("brown","text-highlight"); 
1

Đối với những người nghèo với disregexia hoặc regexophobia:

function replacei(str, sub, f){ 
 
\t let A = str.toLowerCase().split(sub.toLowerCase()); 
 
\t let B = []; 
 
\t let x = 0; 
 
\t for (let i = 0; i < A.length; i++) { 
 
\t \t let n = A[i].length; 
 
\t \t B.push(str.substr(x, n)); 
 
\t \t if (i < A.length-1) 
 
\t \t \t B.push(f(str.substr(x + n, sub.length))); 
 
\t \t x += n + sub.length; 
 
\t } 
 
\t return B.join(''); 
 
} 
 

 
s = 'Foo and FOO (and foo) are all -- Foo.' 
 
t = replacei(s, 'Foo', sub=>'<'+sub+'>') 
 
console.log(t)

Output:

<Foo> and <FOO> (and <foo>) are all -- <Foo>. 
Các vấn đề liên quan