2013-08-03 25 views
6

Tôi luôn phải vật lộn với những điều darn này. Tôi nhớ lại một giảng viên nói với chúng tôi tất cả một lần rằng nếu bạn có một vấn đề mà đòi hỏi bạn sử dụng các biểu thức thông thường để giải quyết nó, bạn trong thực tế bây giờ có 2 vấn đề.Tên người dùng không thể chứa dấu gạch dưới hoặc khoảng thời gian

Vâng, tôi chắc chắn đồng ý với điều này. Regex là thứ mà chúng tôi không sử dụng thường xuyên nhưng khi chúng tôi thực sự thích đọc một số ngôn ngữ ngoài hành tinh (tốt cho tôi) ... Tôi nghĩ tôi sẽ giải quyết để đọc sách và đọc thêm.

Thách thức tôi có được điều này, tôi cần phải xác nhận tên người dùng dựa trên các tiêu chí sau:

  1. có thể chứa các chữ cái, trên và dưới
  2. có thể chứa số
  3. có thể chứa dấu chấm câu (.) và dấu gạch dưới (_)
  4. dấu chấm và dấu gạch dưới không thể liên tiếp tức là __.. không được phép nhưng ._._ sẽ hợp lệ.
  5. tối đa là 20 ký tự trong tổng

Cho đến nay tôi đã điều sau đây: ^[a-zA-Z_.]{0,20}$ nhưng tất nhiên nó cho phép dấu gạch lặp lại và thời gian.

Bây giờ, tôi có thể làm điều này tất cả sai bắt đầu với bộ ký tự hợp lệ và độ dài tối đa. Tôi đã cố gắng (không thành công) để tạo ra một số nhìn xung quanh hoặc nhìn lại hoặc bất cứ điều gì để tìm kiếm sự lặp lại không hợp lệ của khoảng thời gian (.) và gạch dưới (_) không chắc chắn cách tiếp cận hoặc phương pháp nào để phân tích yêu cầu này thành giải pháp regex Là.

Có ai có thể hỗ trợ đề xuất/phương pháp thay thế hoặc hướng tôi đi đúng hướng không?

+0

Bạn đã quên các chữ số trong regex của mình; Ngoài ra, bạn chỉ muốn cho phép chữ cái/chữ số ASCII? Bạn đang sử dụng công cụ regex nào (thông tin bắt buộc cho tất cả các câu hỏi về regex trên StackOverflow, bằng cách này)? –

+3

Biểu thức chính quy vẫn là cách để thực hiện. Nếu bạn sử dụng chúng, tất cả các kiến ​​thức cần thiết để phân tích chuỗi nằm bên trong regex. Nếu bạn không sử dụng chúng, kiến ​​thức ở khắp nơi và bạn có một loạt các vòng lặp, tấn chuỗi hoạt động và hàng triệu trường hợp cạnh mà bạn có thể quên thực hiện và mã kết quả thậm chí còn lỗi hơn và khó đọc hơn. Đừng để giảng viên ngăn cản bạn, Nếu bạn không biết đủ về bất cứ điều gì, thật khó, nếu bạn biết đủ, thật dễ dàng. – escitalopram

+0

Ah có tốt đốm tôi gõ rằng trong sai được cho là^[a-zA-Z0-9_.] Điều này là đủ tốt để đảm bảo tất cả các ký tự ASCII hợp lệ tuy nhiên tôi đang đấu tranh với yêu cầu # 4 mà không chia thành 2 biểu thức. Về công cụ Regex, tôi xác thực cả phía máy khách (Javascript) và phía máy chủ ASP.NET 4.5 – SpaceKat

Trả lời

8

một Đây là một trong những bạn cần:

^(?:[a-zA-Z0-9]|([._])(?!\1)){5,20}$ 

Regular expression visualization

Edit live on Debuggex

Bạn có thể có một bản demo của những gì nó phù hợp với here.


"Hoặc là một char alphanum ([a-zA-Z0-9]), hoặc (|) một dấu chấm hoặc dấu gạch dưới ([._]), nhưng đó không phải được theo sau bởi bản thân ((?!\1)), và từ 5 đến 20 lần ({5,20}). "

  1. (?:X) chỉ đơn giản là một phi chụp nhóm, ví dụ: bạn không thể đề cập đến nó sau đó sử dụng \1, $1 hoặc ?1 cú pháp.

  2. (?!X) được gọi là lookahead phủ định, tức là "không theo sau bởi X".

  3. \1 đề cập đến đầu tiên chụp nhóm. Vì nhóm đầu tiên (?:...){5,20} đã được đặt là không chụp (xem # 1), nhóm chụp đầu tiên là ([._]).

  4. {X,Y} có nghĩa là từ X đến Y lần, bạn có thể thay đổi khi cần.

+2

Đó có thể là giải pháp nhanh nhất. –

+0

Tôi thích tất cả các câu trả lời được cung cấp nhưng mũ ra để sp00m cho giải pháp này mà tôi nghĩ là thanh lịch nhất cho đến nay. Tất nhiên, một khi giải thích tất cả có ý nghĩa :) Khá một thách thức thú vị này, cảm ơn tất cả các bạn đã đóng góp của bạn! – SpaceKat

6

Bạn có thể sử dụng hai negative lookahead assertions cho việc này:

^(?!.*__)(?!.*\.\.)[0-9a-zA-Z_.]{0,20}$ 

Giải thích:

(?! # Assert that it's impossible to match the following regex here: 
.* # Any number of characters 
__ # followed by two underscores in a row 
) # End of lookahead 

Tùy thuộc vào yêu cầu của bạn và trên cơ regex của bạn, bạn có thể thay thế [0-9A-Za-z_.] với [\w.].

@ sp00n nêu ra một điểm tốt: Bạn có thể kết hợp các khẳng định lookahead thành một:

^(?!.*(?:__|\.\.))[0-9a-zA-Z_.]{0,20}$ 

mà có thể là một chút hiệu quả hơn, nhưng là một chút khó khăn hơn để đọc.

+2

Tại sao bạn không sử dụng một lookahead tiêu cực duy nhất với một OR bên trong nó? Của bạn như là là đi qua toàn bộ đầu vào 3 lần. – sp00m

+0

@ sp00m: Tốt. Tôi đã chỉnh sửa câu trả lời của mình. Tôi không chắc nó sẽ ảnh hưởng đến hiệu suất như thế nào, nhưng nó chắc chắn là một lựa chọn tốt. –

6

Đừng cố gắng đẩy điều này vào một regex đơn lẻ. Regex đơn của bạn hoạt động tốt cho tất cả các tiêu chí ngoại trừ # 4. Để làm # 4, chỉ cần thực hiện regex khớp với tên người dùng không hợp lệ và từ chối tên người dùng nếu nó khớp với tên người dùng.Ví dụ (trong giả):

if username.matches("^[a-zA-Z_.]{0,20}$") and !username.matches("__|\\.\\.") { 
    /* accept username */ 
} 
+0

(Không hoàn toàn chắc chắn những gì bạn có nghĩa là "không thể liên tiếp" kể từ khi bạn nói '..' là OK. Nhưng ví dụ này là có nghĩa là để được minh họa anyway). – nneonneo

+0

Nếu đó là nghĩa vụ phải là Java, thì đó là sai. –

+0

'..' không ổn. Đã xảy ra sự cố với định dạng (thiếu) trong bài đăng gốc. –

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