Tham lam vs không tham lam
Sự lặp lại trong regex theo mặc định là tham lam : họ cố gắng khớp càng nhiều đại diện càng tốt và khi điều này không hoạt động và họ phải quay lại, họ cố gắng khớp một lần ít hơn một lần, cho đến khi khớp với toàn bộ mô hình tìm. Kết quả là, khi một trận đấu cuối cùng xảy ra, một sự lặp lại tham lam sẽ khớp với càng nhiều đại diện càng tốt.
Bộ ?
định lượng lặp lại thay đổi hành vi này thành không tham lam , còn được gọi là miễn cưỡng ( ví dụ Java ) (và đôi khi "lười biếng"). Ngược lại, sự lặp lại này trước tiên sẽ cố gắng khớp càng ít lần lặp lại càng tốt và khi điều này không hoạt động và họ phải quay lại, họ bắt đầu kết hợp thêm một lần nữa. Kết quả là, khi một trận đấu cuối cùng xảy ra, một sự lặp lại miễn cưỡng sẽ khớp với số ít đại diện càng tốt.
Người giới thiệu
Ví dụ 1: Từ A đến Z
Hãy so sánh hai mẫu này: A.*Z
vàA.*?Z
.
Cho đầu vào sau:
eeeAiiZuuuuAoooZeeee
Các mẫu mang lại kết quả khớp sau:
Trước tiên hãy tập trung vào những gì A.*Z
. Khi nó phù hợp với cái đầu tiên A
, sự .*
tham lam, đầu tiên cố gắng khớp với càng nhiều .
càng tốt.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Vì Z
không khớp, nên quay lại động cơ và .*
sau đó phải khớp với một ít hơn .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Điều này xảy ra một vài lần nữa, cho đến khi cuối cùng chúng ta đến với điều này:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Bây giờ Z
có thể khớp, vì vậy mô hình tổng thể khớp:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Ngược lại, sự lặp lại miễn cưỡng trong các A.*?Z
trận đấu đầu tiên càng ít .
càng tốt, và sau đó lấy thêm .
khi cần thiết. Điều này giải thích tại sao nó tìm thấy hai kết quả khớp trong đầu vào.
Đây là một đại diện trực quan về những gì hai mẫu phù hợp:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Ví dụ: Một thay thế
Trong nhiều ứng dụng, hai kết quả khớp trong đầu vào trên là những gì mong muốn, do đó, một sự miễn cưỡng .*?
được sử dụng thay vì tham lam .*
để ngăn chặn việc vượt qua. Tuy nhiên, đối với mẫu cụ thể này, có một cách thay thế tốt hơn, sử dụng lớp ký tự phủ định.
Mẫu A[^Z]*Z
cũng tìm thấy hai kết quả khớp giống như A.*?Z
mẫu cho đầu vào ở trên ( như đã thấy trên ideone.com ). [^Z]
là những gì được gọi là một lớp nhân vật phủ định : nó phù hợp với bất cứ điều gì nhưng Z
.
Sự khác biệt chính giữa hai mẫu là về hiệu năng: nghiêm ngặt hơn, lớp ký tự bị phủ định chỉ có thể khớp với một cách cho một đầu vào nhất định. Không thành vấn đề nếu bạn sử dụng công cụ sửa đổi tham lam hoặc miễn cưỡng cho mẫu này. Trong thực tế, trong một số hương vị, bạn thậm chí có thể làm tốt hơn và sử dụng cái được gọi là định lượng sở hữu, hoàn toàn không quay lại.
Người giới thiệu
Ví dụ 2: Từ A đến ZZ
Ví dụ này nên có tính minh họa: nó cho thấy các mẫu lớp nhân vật tham lam, miễn cưỡng và phủ định khớp với các đầu vào khác nhau như thế nào.
eeAiiZooAuuZZeeeZZfff
Đây là các kết quả khớp cho đầu vào trên:
Đây là một đại diện trực quan của những gì họ phù hợp:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
Chủ đề liên quan
Đây là các liên kết đến câu hỏi và câu trả lời trên stackoverflow bao gồm một số chủ đề có thể được quan tâm.
Một sự lặp lại tham lam có thể vượt xa người khác