2009-09-29 24 views
5

Điều tôi cần là kiểm tra xem chuỗi đã cho có khớp một phần với regex đã cho hay không. Ví dụ: đối với regex ab[0-9]c, các chuỗi "a", "ab", "ab3" và "b3c" sẽ "khớp", nhưng không phải là chuỗi "d", "abc" hoặc "a3c". Những gì tôi đã làm là clunky a(?:b(?:[0-9](?:c)?)?)? (chỉ hoạt động đối với một số kết quả khớp một phần, cụ thể là những từ "bắt đầu"), nhưng vì đây là một phần của API, tôi muốn cung cấp cho người dùng trực quan hơn cách nhập regexps phù hợp của họ.Có cách nào thanh lịch để thực hiện các kết quả regex một phần trong Java không?

Trong trường hợp mô tả không rõ ràng (và tôi nhận ra nó có thể không!), Điều này sẽ được sử dụng để xác thực nhập văn bản trên hộp văn bản. Tôi muốn ngăn chặn bất kỳ chỉnh sửa nào có thể dẫn đến một chuỗi không hợp lệ, nhưng tôi không thể chỉ khớp chuỗi với một regex thông thường, vì cho đến khi nó được nhập đầy đủ, nó sẽ không khớp. Ví dụ, sử dụng regex ở trên (ab[0-9]c), khi tôi cố gắng nhập 'a', nó không được phép, vì chuỗi "a" không khớp với regex.

Về cơ bản, đó là một loại đảo ngược startsWith() hoạt động trên regexps. (new Pattern("ab[0-9]c").startsWith("ab3") phải trả lại true.)

Bất kỳ ý tưởng nào?

+0

FYI: 'a (?: B (?: [0-9] (?: c)?)?)?' Sẽ khớp * bất kỳ * chuỗi nào chứa "a", chẳng hạn như "jazz ". Bạn muốn sử dụng '^ a (?: B (?: [0-9] (?: c)?)?)? $' Để bạn khớp với toàn bộ chuỗi. – Kip

+0

Tất cả các regex khách hàng có sử dụng đơn giản như 'ab [0-9] c' hay bạn sẽ cần kết hợp phức tạp hơn (tức là với các nhóm con)? – Kip

+0

Rất tiếc ... vâng,^và $ được thêm vào regexp tự động, đó là lý do tôi bỏ qua để thêm chúng, cảm ơn. Và không, các regexps không đơn giản như vậy, chúng có thể khá phức tạp, mặc dù không xa như yêu cầu các nhóm con. – Tonio

Trả lời

6

Có phải Matcher.hitEnd() bạn đang tìm kiếm gì không?

Pattern thePattern = Pattern.compile(theRegexString); 
Matcher m = thePattern.matcher(theStringToTest); 
if (m.matches()) { 
    return true; 
} 
return m.hitEnd(); 
+0

Đẹp! Nó gần như hoạt động. Nó chắc chắn hoạt động như một sự thay thế cho những gì tôi đang làm. Nó vẫn không hoạt động đối với các kết quả khớp một phần (ví dụ, "b3c" là một phần đuôi phù hợp với 'ab [0-9] c'), nhưng giải pháp hiện tại của tôi cũng không xử lý được. – Tonio

+0

Đúng là 'hitEnd()' phục vụ cùng mục đích như giải pháp riêng của OP phá vỡ regex thành các nhóm tùy chọn kế tiếp. Nhưng vẫn không có cách nào để phát hiện một phần khớp không khớp với phần đầu của regex. –

4

Mặc dù có thể có một số thủ thuật có sẵn, nhưng cách của bạn có lẽ là ngữ nghĩa tốt nhất. Nó mô tả chính xác những gì bạn đang tìm kiếm.

Tuy nhiên, vấn đề lớn hơn là liệu bạn có thực sự cần xác thực mỗi lần một ký tự được nhập vào hộp văn bản hay không. Tại sao bạn không thể chỉ xác nhận nó một lần ở cuối và tiết kiệm cho mình một số nhức đầu?

+0

"Tại sao", thực sự ...: (Bởi vì khách hàng (tm) quyết định nó như vậy. Vấn đề với cách tôi đang làm nó, ngoài thực tế là nó không thân thiện (tôi phải giải thích cho người dùng) của API về các regexps một phần lạ, v.v.), là nó sẽ không khớp với chuỗi khớp với END của regex. Trong ví dụ trên, nó sẽ không khớp với "3c", sẽ hợp lệ vì bạn luôn có thể quay lại và thêm "ab" vào đầu. – Tonio

+0

Khách hàng có thực sự xác định rằng nó phải được thực hiện bởi một regex không? Hay là phần đặc biệt của thiết kế đến từ phía kỹ thuật? – Yishai

+0

Khách hàng không chỉ định rằng nó phải được thực hiện bởi một regex, đó là quyết định thiết kế của chúng tôi. Ban đầu nó được thực hiện bằng cách kết hợp chuỗi đơn giản, nhưng cuối cùng chúng tôi quyết định sử dụng regexps vì một số mẫu có thể trở nên khá phức tạp. – Tonio

2

Đây là một regex mà có thể giải quyết ví dụ cụ thể của bạn:

^(?:a|b|[0-9]|c|ab|b[0-9]|[0-9]c|ab[0-9]|b[0-9]c|ab[0-9]c)?$ 

Nói chung, nếu bạn có thể phá vỡ các regex xuống thành nhiều phần nguyên tử, bạn có thể OR hợp tất cả các nhóm có thể có của họ, nhưng nó là lớn và xấu xí. Trong trường hợp này, có 4 phần (a, b, [0-9] và c), vì vậy bạn phải HOẶC cùng nhau 4 + 3 + 2 + 1 = 10 khả năng. (Đối với các bộ phận n, đó là (n × (n +1))/2 khả năng). Bạn có thể tạo ra thuật toán này, nhưng nó sẽ là một nỗi đau lớn để kiểm tra. Và bất cứ điều gì phức tạp (như một phân nhóm) sẽ rất khó để có được quyền.

Một giải pháp tốt hơn có lẽ là chỉ để có một thông báo bên cạnh trường nhập cho người dùng biết "không đủ thông tin" hoặc một cái gì đó, và khi họ thay đổi nó thành hộp kiểm màu xanh lá cây hoặc gì đó. Dưới đây là một bài báo gần đây từ A List Apart để cân nhắc những ưu và nhược điểm của các cách tiếp cận khác nhau đối với vấn đề này: Inline Validation in Web Forms.

+0

Đây chính xác là những gì tôi đang cố gắng tránh ... regexps vô ích (OR'ed trong ví dụ của bạn, có chứa các nhóm con tùy chọn ở cuối trong ví dụ của tôi). :( Thật không may, giải pháp tốt hơn của bạn là không thể chấp nhận bởi khách hàng. Điều họ yêu cầu là chặn nhập văn bản của các ký tự không hợp lệ (các ký tự có nghĩa là bất hợp pháp không dẫn đến chuỗi hợp lệ) và phản hồi trực quan của chuỗi hoàn toàn hợp lệ (có nghĩa là, như được thực hiện, nền của hộp văn bản thay đổi màu sắc khi chuỗi khớp hoàn toàn với regex) – Tonio

+0

Có lẽ bạn có thể có hai bước, một bước chạy 'ab [0-9] c' và cho biết chuỗi đầy đủ là hợp lệ, và một trong đó chạy regex lớn để nói nếu những gì họ đã nhập * có thể * là hợp lệ.Bạn có thể chạy regex lớn trên sự kiện keyPressed, và nếu thất bại, bạn trả về false (tức là không cho phép người dùng nhập nhân vật đó) – Kip

+0

Nếu tôi có thể tạo ra các thuật toán này theo thuật toán, nó sẽ là một giải pháp hợp lệ. Việc tạo ra chúng cho các regex đơn giản không nên quá nhiều vấn đề, nhưng tiếc là không phải tất cả lại gexps được sử dụng rất đơn giản. – Tonio

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