Làm thế nào để biến biểu thức chính quy thành không tham lam?


227

Tôi đang sử dụng jQuery. Tôi có một chuỗi với một khối các ký tự đặc biệt (bắt đầu và kết thúc). Tôi muốn có được văn bản từ khối ký tự đặc biệt đó. Tôi đã sử dụng một đối tượng biểu thức chính quy để tìm trong chuỗi. Nhưng làm thế nào tôi có thể bảo jQuery tìm nhiều kết quả khi có hai ký tự đặc biệt trở lên?

HTML của tôi:

<div id="container">
    <div id="textcontainer">
     Cuc chiến pháp lý gia [|cơ thử|nghim|] th trường [|test2|đây là test ln 2|] chng khoán [|Mỹ|day la nuoc my|] và ngân hàng đầu tư quyn lc nht Ph Wall mi ch bt đầu.
    </div>
</div>

và mã JavaScript của tôi:

$(document).ready(function() {
  var takedata = $("#textcontainer").text();
  var test = 'abcd adddb';
  var filterdata = takedata.match(/(\[.+\])/);

  alert(filterdata); 

  //end write js 
});

Kết quả của tôi là: [| cơ try to | nghiệm |] thị trường [| test2 | here is thử nghiệm lần 2 |] security [| Mỹ | ngày la nuoc tôi |] . Nhưng đây không phải là kết quả tôi muốn :(. Làm thế nào để có được [văn bản] cho lần 1 và [bản demo] cho lần 2?


Tôi vừa hoàn thành công việc của mình sau khi tìm kiếm thông tin trên internet ^^. Tôi tạo mã như thế này:

var filterdata = takedata.match(/(\[.*?\])/g);
  • kết quả của tôi là: [| xông vào | hạ |], [| test2 | miếng là thử nghiệm 2 |] điều này đúng!. nhưng tôi không thực sự hiểu điều này. Bạn có thể trả lời tại sao của tôi?

Câu trả lời:


492

Các sửa đổi regex không tham lam giống như các phần đối nghịch tham lam của chúng nhưng ?ngay lập tức theo sau chúng:

*  - zero or more
*? - zero or more (non-greedy)
+  - one or more
+? - one or more (non-greedy)
?  - zero or one
?? - zero or one (non-greedy)

29
có thể hữu ích để lưu ý rằng ?theo cách riêng của nó 'một hoặc không' (nhưng là tham lam!). Ví dụ 'bb'.replace(/b?/, 'a') //'ab''bb'.replace(/c?/, 'a') //'abb'
Hashbrown

1
Làm thế nào mà c không có gì ở đó
Muhammad Umer

1
@MuhammadUmer Tôi nghĩ rằng ông đã gợi ý rằng bởi vì csẽ không phù hợp, nhưng bạn có ?, được 0 or 1, sau đó nó sẽ phù hợp 0 number of c characters, do đó thay thế nó. Tôi không biết làm thế nào nó hoạt động, bởi vì nó không biên dịch trong bất kỳ công cụ regex nào tôi đã thử 😢
Noctis

35

Bạn đúng rằng sự tham lam là một vấn đề:

--A--Z--A--Z--
  ^^^^^^^^^^
     A.*Z

Nếu bạn muốn kết hợp cả hai A--Z, bạn phải sử dụng A.*?Z( ?làm cho *"miễn cưỡng" hoặc lười biếng).

Đôi khi có những cách tốt hơn để làm điều này, ví dụ,

A[^Z]*+Z

Điều này sử dụng lớp ký tự phủ định và bộ định lượng sở hữu, để giảm quay lui và có khả năng hiệu quả hơn.

Trong trường hợp của bạn, regex sẽ là:

/(\[[^\]]++\])/

Thật không may, regex Javascript không hỗ trợ bộ định lượng sở hữu, vì vậy bạn chỉ cần thực hiện với:

/(\[[^\]]+\])/

Xem thêm


Tóm tắt nhanh

*   Zero or more, greedy
*?  Zero or more, reluctant
*+  Zero or more, possessive

+   One or more, greedy
+?  One or more, reluctant
++  One or more, possessive

?   Zero or one, greedy
??  Zero or one, reluctant
?+  Zero or one, possessive

Lưu ý rằng các bộ định lượng miễn cưỡng và sở hữu cũng có thể áp dụng cho các {n,m}cấu trúc lặp lại hữu hạn .

Ví dụ trong Java:

System.out.println("aAoZbAoZc".replaceAll("A.*Z", "!"));  // prints "a!c"
System.out.println("aAoZbAoZc".replaceAll("A.*?Z", "!")); // prints "a!b!c"

System.out.println("xxxxxx".replaceAll("x{3,5}", "Y"));  // prints "Yx"
System.out.println("xxxxxx".replaceAll("x{3,5}?", "Y")); // prints "YY"

tôi sao chép regex của bạn vào công việc của tôi và kết quả là: bộ định lượng không hợp lệ + \]) [Phá vỡ lỗi này] var filterdata = takenata.match (/ (\ [[^ \]] ++ \]) /); \ n ( firebugs + Firefox) có gì sai?
Rueta

@Rueta: rõ ràng hương vị Javascript không hỗ trợ sở hữu. Tôi đã chỉnh sửa câu trả lời của mình để phản ánh sự thật này. Bạn chỉ có thể sử dụng một +thay vì hai.
đa gen

1
Mặc dù các nhóm nguyên tử có thể được sử dụng thay cho các bộ lượng tử sở hữu, JavaScript cũng không hỗ trợ các nhóm nguyên tử. Nhưng có một sự thay thế thứ ba, hãy xem điều này: instanceof.me/post/52245507631/NH -you can emulate atomic grouping with LookAhead. (?>a) becomes (?=(a))\1
Roland Pihlakas

2
Đây là câu trả lời Java cho câu hỏi JavaScript và Java! = JavaScript. Độc giả, hãy lưu ý.
Roshambo

3

Tôi tin rằng nó sẽ như thế này

takedata.match(/(\[.+\])/g);

các gở cuối có nghĩa toàn cầu, vì vậy nó không dừng lại ở trận đấu đầu tiên.


vâng, bạn đang ở trong / g. Tôi vừa hoàn thành công việc của mình với câu trả lời của bạn / g ^^. Nhưng khi tôi thực hiện thường xuyên /(\[.+\[)/g thì kết quả của tôi là: [| canh | | | | | [| [[test2 | tập là thử nghiệm 2 |] lồng [[Mỹ | day la nuoc của tôi |] :(
Rueta
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.