2013-03-28 16 views
9

Tôi muốn thay thế tất cả các chuỗi được đính kèm bởi - thành các chuỗi kèm theo ~, nhưng không phải nếu chuỗi này một lần nữa được kèm theo *.Không thay thế regex nếu nó được kèm theo bởi một ký tự

Như một ví dụ, chuỗi này ...

The -quick- *brown -f-ox* jumps. 

... nên trở thành ...

The ~quick~ *brown -f-ox* jumps. 

Chúng ta thấy - chỉ được thay thế nếu nó là không trong *<here>*.

My javascript regex cho bây giờ (mất không chăm sóc cho dù nó được bao bọc bởi * hay không):

var message = source.replace(/-(.[^-]+?)-/g, "~$1~"); 

Chỉnh sửa: Lưu ý rằng nó có thể là trường hợp đó có một số lẻ của * s .

+7

Tại sao bạn nên downvote? – poitroae

+0

yup tôi ngạc nhiên, một câu hỏi hay. – Jai

+2

Điều gì khi có số ký tự lẻ *? Ví dụ. 'The * -quick- * brown * -f-ox * nhảy * .' Những ký tự' -' nào nên được thay thế và tại sao? –

Trả lời

2

Đó là một điều khó khăn để làm với các biểu thức chính quy. Tôi nghĩ rằng những gì tôi muốn làm là một cái gì đó như thế này:

var msg = source.replace(/(-[^-]+-|\*[^*]+\*)/g, function(_, grp) { 
    return grp[0] === '-' ? grp.replace(/^-(.*)-$/, "~$1~") : grp; 
}); 

jsFiddle Demo

Đó tìm kiếm hoặc- hoặc * nhóm, và chỉ thực hiện việc thay thế trên những tiêu tan. Nói chung, cú pháp "lồng" là thử thách (hoặc không thể) với các biểu thức chính quy. (Và tất nhiên như một bình luận trên các ghi chú câu hỏi, có những trường hợp đặc biệt — metacharacters lủng lẳng — mà làm phức tạp này quá.)

+1

Ví dụ làm việc: http://jsfiddle.net/Zb6BU/ - không chắc chắn tại sao điều này không nhận được phiếu bầu, điều này hoạt động giống như dự định! +1 –

+0

@mcpDESIGNS: Các câu trả lời khác cũng đang hoạt động :-) – Bergi

+0

@Bergi Tôi thấy rằng bây giờ, +1 cho tất cả :) haha ​​ –

1

tôi sẽ giải quyết nó bằng cách phân chia các mảng dựa trên * và sau đó thay thế chỉ có chỉ số chẵn. Phù hợp với sao không cân bằng là phức tạp hơn, nó liên quan đến việc biết liệu chỉ số mục cuối cùng là số lẻ hoặc thậm chí:

'The -quick- *brown -f-ox* jumps.' 
    .split('*') 
    .map(function(item, index, arr) { 
     if (index % 2) { 
      if (index < arr.length - 1) { 
       return item; // balanced 
      } 
      // not balanced 
      item = '*' + item; 
     } 
     return item.replace(/\-([^-]+)\-/, '~$1~'); 
    }) 
    .join(''); 

Demo

+0

Điều gì nếu chuỗi chứa một '*' không phải là một phần của một cặp? ví dụ. ''The -quick- * brown -f-ox jumps.'' Nếu tôi hiểu đúng, trong trường hợp này cả hai' -quick-'và' -f-'nên được thay thế, nhưng chỉ' -quick-'sẽ. –

+0

@KenB Giả sử rằng các ngôi sao được cân bằng tốt :) –

+0

Tùy thuộc vào ngữ cảnh, đó là một giả định khá lớn. –

1

tìm hiểu xem một trận đấu là không được bao bọc bởi một số delimiters là một nhiệm vụ rất phức tạp - xem thêm this example. Lookaround có thể giúp, nhưng JS chỉ hỗ trợ lookahead. Vì vậy, chúng ta có thể viết lại "không bao quanh bởi ~" thành "tiếp theo là một số chẵn hoặc ~", và trận đấu trên rằng:

source.replace(/-([^-]+)-(?=[^~]*([^~]*~[^~]*~)*$)/g, "~$1~"); 

Nhưng tốt hơn chúng tôi phù hợp trên cả hai -*, để chúng ta tiêu thụ bất cứ điều gì được bọc trong * s cũng và sau đó có thể quyết định trong một hàm callback không thay thế nó:

source.replace(/-([^-]+)-|\*([^*]+)\*/g, function(m, hyp) { 
    if (hyp) // the first group has matched 
     return "~"+hyp+"~"; 
    // else let the match be unchanged: 
    return m; 
}); 

này có lợi thế của việc có thể để xác định tốt hơn "kèm theo", ví dụ:bằng cách thêm các ranh giới từ vào "bên trong", để xử lý tốt hơn các mẫu không hợp lệ (số lẻ * các ký tự như được đề cập bởi @Maras chẳng hạn) - regex hiện tại chỉ mất hai lần xuất hiện tiếp theo.

0

Phiên bản rút gọn của câu trả lời rất rõ ràng của Jack.

source.split(/(\*[^*]*\*)/g).map(function(x,i){ 
return i%2?x:x.replace(/-/g,'~'); 
}).join(''); 

Có vẻ như hoạt động, Chúc mừng.

Các vấn đề liên quan