Biểu thức chính quy hoàn toàn tuân thủ RFC 822 không hiệu quả và khó hiểu do độ dài của nó. May mắn thay, RFC 822 đã được thay thế hai lần và thông số kỹ thuật hiện tại cho địa chỉ email là RFC 5322. RFC 5322 dẫn đến một biểu thức chính quy có thể hiểu được nếu được nghiên cứu trong vài phút và đủ hiệu quả để sử dụng thực tế
Có thể tìm thấy một biểu thức chính quy tuân thủ RFC 5322 ở đầu trang tại http. //emailregex. com/ nhưng sử dụng mẫu địa chỉ IP trôi nổi trên internet với một lỗi cho phép
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
0 đối với bất kỳ giá trị thập phân byte không dấu nào trong một địa chỉ được phân cách bằng dấu chấm, điều này là bất hợp pháp. Phần còn lại của nó có vẻ phù hợp với ngữ pháp RFC 5322 và vượt qua một số bài kiểm tra bằng cách sử dụng import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
1, bao gồm cả trường hợp tên miền, địa chỉ IP, tên xấu và tên tài khoản có và không có dấu ngoặc képSửa lỗi
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
0 trong mẫu IP, chúng tôi có được biểu thức chính quy hoạt động và khá nhanh. [Cạo phiên bản được kết xuất, không phải phiên bản đánh dấu, để biết mã thực tế. ][?. [a-z0-9. #$%&'*+/=?^_`{. }~-]+[?. \. [a-z0-9. #$%&'*+/=?^_`{. }~-]+]*. "[?. [\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]. \\[\x01-\x09\x0b\x0c\x0e-\x7f]]*"]@[?. [?. [a-z0-9][?. [a-z0-9-]*[a-z0-9]]?\. ]+[a-z0-9][?. [a-z0-9-]*[a-z0-9]]?. \[[?. [?. [2[5[0-5]. [0-4][0-9]]. 1[0-9][0-9]. [1-9]?[0-9]]]\. ]{3}[?. [2[5[0-5]. [0-4][0-9]]. 1[0-9][0-9]. [1-9]?[0-9]]. [a-z0-9-]*[a-z0-9]. [?. [\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]. \\[\x01-\x09\x0b\x0c\x0e-\x7f]]+]\]]
hoặc
[?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+[?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+]*|"[?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]]*"]@[?:[?:[a-z0-9][?:[a-z0-9-]*[a-z0-9]]?\.]+[a-z0-9][?:[a-z0-9-]*[a-z0-9]]?|\[[?:[?:[2[5[0-5]|[0-4][0-9]]|1[0-9][0-9]|[1-9]?[0-9]]]\.]{3}[?:[2[5[0-5]|[0-4][0-9]]|1[0-9][0-9]|[1-9]?[0-9]]|[a-z0-9-]*[a-z0-9]:[?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]]+]\]]
Đây là sơ đồ của máy trạng thái hữu hạn cho biểu thức chính quy ở trên rõ ràng hơn chính biểu thức chính quy
Các mẫu phức tạp hơn trong Perl và PCRE [thư viện regex được sử dụng. g. trong PHP] có thể phân tích chính xác RFC 5322 mà không gặp trở ngại nào. Python và C# cũng có thể làm điều đó, nhưng chúng sử dụng một cú pháp khác với hai cú pháp đầu tiên. Tuy nhiên, nếu bạn buộc phải sử dụng một trong nhiều ngôn ngữ khớp mẫu kém hiệu quả hơn, thì tốt nhất bạn nên sử dụng trình phân tích cú pháp thực
Điều quan trọng là phải hiểu rằng việc xác thực địa chỉ đó theo RFC hoàn toàn không cho bạn biết liệu địa chỉ đó có thực sự tồn tại ở miền được cung cấp hay không hoặc liệu người nhập địa chỉ có phải là chủ sở hữu thực sự của địa chỉ đó hay không. Mọi người đăng ký người khác vào danh sách gửi thư theo cách này mọi lúc. Việc khắc phục yêu cầu một loại xác thực phức tạp hơn liên quan đến việc gửi cho địa chỉ đó một thông báo bao gồm mã thông báo xác nhận có nghĩa là được nhập trên cùng một trang web với địa chỉ
Mã thông báo xác nhận là cách duy nhất để biết bạn đã nhận được địa chỉ của người nhập nó. Đây là lý do tại sao hầu hết các danh sách gửi thư hiện sử dụng cơ chế đó để xác nhận đăng ký. Xét cho cùng, bất kỳ ai cũng có thể đặt xuống
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
3 và điều đó thậm chí sẽ được phân tích là hợp pháp, nhưng không có khả năng đó là người ở đầu dây bên kiaĐối với PHP, bạn không nên sử dụng mẫu được cung cấp trong Xác thực địa chỉ E-Mail bằng PHP, Cách phù hợp mà tôi đã trích dẫn
Có một số mối nguy hiểm là việc sử dụng phổ biến và mã hóa cẩu thả phổ biến sẽ thiết lập một tiêu chuẩn thực tế cho các địa chỉ e-mail hạn chế hơn so với tiêu chuẩn chính thức được ghi lại
Điều đó không tốt hơn tất cả các mẫu không phải RFC khác. Nó thậm chí còn không đủ thông minh để xử lý ngay cả RFC 822 chứ chưa nói đến RFC 5322. Cái này, tuy nhiên, là
Nếu bạn muốn trở nên lạ mắt và khoa trương, hãy triển khai một công cụ trạng thái hoàn chỉnh. Một biểu thức chính quy chỉ có thể hoạt động như một bộ lọc thô sơ. Vấn đề với biểu thức chính quy là nói với ai đó rằng địa chỉ e-mail hoàn toàn hợp lệ của họ không hợp lệ [dương tính giả] vì biểu thức chính quy của bạn không thể xử lý nó chỉ là thô lỗ và bất lịch sự từ quan điểm của người dùng. Một công cụ trạng thái cho mục đích này có thể vừa xác thực và thậm chí sửa các địa chỉ email mà nếu không sẽ bị coi là không hợp lệ vì nó phân tách địa chỉ email theo từng RFC. Điều này cho phép trải nghiệm thú vị hơn, như
Địa chỉ email được chỉ định 'my email@address,com' không hợp lệ. Ý bạn là 'địa chỉ email@của tôi. com'?
Xem thêm Xác thực địa chỉ email, bao gồm các nhận xét. Hoặc So sánh Địa chỉ E-mail Xác thực Biểu thức Chính quy
Trình diễn gỡ lỗi
Regex – Biểu thức chính quy để khớp với dòng không chứa từ
Quan điểm cho rằng regex không hỗ trợ kết hợp nghịch đảo không hoàn toàn đúng. Bạn có thể bắt chước hành vi này bằng cách sử dụng cái nhìn xung quanh tiêu cực
^[[?!hede].]*$
Biểu thức chính quy ở trên sẽ khớp với bất kỳ chuỗi hoặc dòng nào mà không ngắt dòng, không chứa chuỗi [phụ] 'hede'. Như đã đề cập, đây không phải là thứ regex "giỏi" [hoặc nên làm], nhưng vẫn có thể
Và nếu bạn cũng cần khớp các ký tự ngắt dòng, hãy sử dụng công cụ sửa đổi DOT-ALL [dấu
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
4 trong mẫu sau]/^[[?!hede].]*$/s
hoặc sử dụng nó nội tuyến
________số 8[trong đó
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
5 là các dấu phân cách biểu thức chính quy, tôi. e. , không phải là một phần của mẫu]Nếu không có công cụ sửa đổi DOT-ALL, bạn có thể bắt chước hành vi tương tự với lớp ký tự
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
6import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
1Giải trình
Một chuỗi chỉ là một danh sách gồm
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
7 ký tự. Trước và sau mỗi ký tự, có một chuỗi trống. Vì vậy, một danh sách gồm các ký tự import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
7 sẽ có các chuỗi rỗng import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
9. Xét chuỗi import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
50import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
6trong đó
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
51 là các chuỗi rỗng. Regex import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
52 nhìn về phía trước để xem liệu không có chuỗi con import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
53 nào được nhìn thấy hay không và nếu trường hợp đó xảy ra [để nhìn thấy thứ khác], thì import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
54 [dấu chấm] sẽ khớp với bất kỳ ký tự nào ngoại trừ dấu ngắt dòng. Nhìn xung quanh còn được gọi là xác nhận độ rộng bằng không vì chúng không sử dụng bất kỳ ký tự nào. Họ chỉ khẳng định/xác nhận điều gì đóVì vậy, trong ví dụ của tôi, mọi chuỗi rỗng trước tiên được xác thực để xem liệu có không có
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
53 phía trước hay không, trước khi một ký tự được sử dụng bởi import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
54 [dấu chấm]. Regex import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
52 sẽ chỉ làm điều đó một lần, vì vậy nó được gói trong một nhóm và lặp lại 0 hoặc nhiều lần. import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
58. Cuối cùng, điểm bắt đầu và kết thúc đầu vào được cố định để đảm bảo toàn bộ đầu vào được sử dụng. import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
59Như bạn có thể thấy, đầu vào
import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
50 sẽ không thành công vì trên [?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+[?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+]*|"[?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]]*"]@[?:[?:[a-z0-9][?:[a-z0-9-]*[a-z0-9]]?\.]+[a-z0-9][?:[a-z0-9-]*[a-z0-9]]?|\[[?:[?:[2[5[0-5]|[0-4][0-9]]|1[0-9][0-9]|[1-9]?[0-9]]]\.]{3}[?:[2[5[0-5]|[0-4][0-9]]|1[0-9][0-9]|[1-9]?[0-9]]|[a-z0-9-]*[a-z0-9]:[?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]]+]\]]
1, biểu thức chính quy [?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+[?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+]*|"[?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]]*"]@[?:[?:[a-z0-9][?:[a-z0-9-]*[a-z0-9]]?\.]+[a-z0-9][?:[a-z0-9-]*[a-z0-9]]?|\[[?:[?:[2[5[0-5]|[0-4][0-9]]|1[0-9][0-9]|[1-9]?[0-9]]]\.]{3}[?:[2[5[0-5]|[0-4][0-9]]|1[0-9][0-9]|[1-9]?[0-9]]|[a-z0-9-]*[a-z0-9]:[?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f]]+]\]]
2 không thành công [có import re
s = "//[ipaddress]/SaveData/127.0.0.1/00-0C-F1-56-98-AD/"
re.search[r'[[0-9A-F]{2}[:-]]{5}[[0-9A-F]{2}]', s, re.I].group[]
'00-0C-F1-56-98-AD'
re.search[r'[[2[0-5]|1[0-9]|[0-9]]?[0-9]\.]{3}[[2[0-5]|1[0-9]|[0-9]]?[0-9]]', s, re.I].group[]
'127.0.0.1'
53 ở phía trước. ]