2012-02-25 18 views
5

Tôi đang sử dụng một regex để tìm:Regex lookahead

test:? 

Tiếp theo là bất kỳ ký tự cho đến khi nó chạm tiếp theo:

test:? 

Bây giờ khi tôi chạy regex này tôi đã thực hiện:

((?:test:\?)(.*)(?!test:\?)) 

Trên văn bản này:

test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2 

tôi mong đợi để có được:

test:?foo2=bar2&baz2=foo2 

test:?foo=bar&baz=foo 

test:?foo2=bar2&baz2=foo2 

Nhưng thay vì nó phù hợp với tất cả mọi thứ. Có ai có nhiều kinh nghiệm về regex biết tôi đã đi sai không? Tôi đã sử dụng regexes cho phù hợp với mô hình trước đây nhưng đây là kinh nghiệm đầu tiên của tôi về cách nhìn/aheads.

Cảm ơn trước sự giúp đỡ nào/lời khuyên/con trỏ :-)

+0

Bạn chỉ cần muốn chia trên 'test:?'? Nếu bạn đang có, môi trường của bạn sẽ cung cấp một cách để làm điều đó mà không có biểu thức thông thường. –

Trả lời

4

Tôi đoán bạn có thể khám phá một phiên bản tham lam.
(mở rộng)

(test:\? (?: (?!test:\?)[\s\S])*)

+0

Cảm ơn bạn. Điều này làm việc hoàn hảo và tôi đã học được nhiều hơn về cú pháp. – james

-1

Bạn có thể muốn ((?:test:\?)(.*?)(?=test:\?)), mặc dù bạn chưa nói với chúng tôi những gì ngôn ngữ mà bạn đang sử dụng để lái xe regexes.

Các .*? trận càng ít nhân vật càng tốt mà không ngăn chặn toàn bộ chuỗi từ phù hợp, nơi .* trận như nhiều càng tốt (là tham lam).

Tùy thuộc, một lần nữa, về ngôn ngữ bạn đang sử dụng để làm điều này, bạn có thể cần phải khớp, sau đó cắt chuỗi, sau đó khớp lại hoặc gọi một số hàm match_all loại ngôn ngữ cụ thể.

Bằng cách này, bạn không cần phải neo một regex sử dụng một lookahead (bạn chỉ có thể phù hợp với mô hình để tìm kiếm, thay vì), vì vậy đây sẽ (rất có thể) làm trong trường hợp của bạn:

test:[?](.*?)test:[?] 
+1

Nếu bạn đang đi theo cách tiếp cận đó, thì bạn cần thay đổi '?!' Thành '? ='. – ruakh

+0

@ruakh Right. Thay đổi, cảm ơn. – Borealid

+1

-1, lookahead là cần thiết. Nếu không có nó, tất cả các trận đấu bắt buộc khác sẽ không khớp vì 'test:' đã được tiêu thụ. – Qtax

0

Ba vấn đề:

  • (?!) là một lookahead khẳng định tiêu cực. Thay vào đó, bạn muốn (?=) yêu cầu điều tiếp theo là test:?.

  • .* là tham lam; bạn muốn nó không tham lam để bạn lấy chunk đầu tiên.

  • Bạn cũng muốn đoạn cuối cùng, vì vậy, bạn cũng muốn kết hợp cả $ ở cuối.

End kết quả:

(?:test:\?)(.*?)(?=test:\?|$) 

Tôi cũng đã loại bỏ các nhóm bên ngoài, nhìn thấy không có điểm trong nó. Tất cả các công cụ RE mà tôi biết để cho phép bạn truy cập vào nhóm 0 là trận đấu đầy đủ, hoặc một số cách khác như vậy (mặc dù có lẽ không phải khi tìm tất cả các trận đấu). Bạn có thể đặt nó trở lại nếu bạn cần.

(Điều này làm việc trong PCRE; không chắc chắn nếu nó sẽ làm việc với POSIX biểu thức thông thường, như tôi không có thói quen làm việc với họ.)

Nếu bạn chỉ muốn chia trên test:?, mặc dù, biểu thức chính quy là công cụ sai. Tách các chuỗi bằng cách sử dụng hỗ trợ sẵn có của ngôn ngữ cho những thứ như vậy.

Python:

>>> re.findall('(?:test:\?)(.*?)(?=test:\?|$)', 
... 'test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2') 
['foo2=bar2&baz2=foo2', 'foo=bar&baz=foo', 'foo2=bar2&baz2=foo2'] 
2

Chương trình Perl dưới đây

#! /usr/bin/env perl 

use strict; 
use warnings; 

$_ = "test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2"; 

while (/(test:\? .*?) (?= test:\? | $)/gx) { 
    print "[$1]\n"; 
} 

tạo ra kết quả mong muốn từ câu hỏi của bạn, cộng với dấu ngoặc để nhấn mạnh.

[test:?foo2=bar2&baz2=foo2] 
[test:?foo=bar&baz=foo] 
[test:?foo2=bar2&baz2=foo2]

Hãy nhớ rằng regex quantifiers are greedy và muốn gobble lên nhiều nhất có thể mà không phá vỡ trận đấu. Mỗi phân đoạn con để chấm dứt càng sớm càng tốt, có nghĩa là .*? ngữ nghĩa.

Mỗi phân cụm kết thúc bằng một số khác test:? hoặc cuối chuỗi, mà chúng tôi tìm kiếm với (?=...) bề mặt không có chiều rộng được bao quanh khoảng | cho các lựa chọn thay thế.

Mẫu trong mã ở trên sử dụng Perl’s /x regex switch để dễ đọc. Tùy thuộc vào ngôn ngữ và thư viện bạn sử dụng ’, bạn có thể cần xóa khoảng trắng thừa.

+0

Tôi sử dụng sytnax của bạn trong một thử nghiệm regex nhưng trận đấu vẫn cho tôi một chuỗi có chứa hai "test :?" dây. Tôi đang sử dụng Java vì vậy tôi giả sử nó có thể bằng cú pháp liên quan? (Tôi đã xóa các khoảng trắng để thử nghiệm). Cảm ơn sự giúp đỡ của bạn mặc dù tôi đã học được nhiều hơn nữa. – james

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