Làm thế nào nó hoạt động?
Hãy xem lý thuyết automata
Nói tóm lại, mỗi biểu thức chính quy có một máy tự động hữu hạn tương đương và có thể được biên dịch và tối ưu hóa thành máy tự động hữu hạn. Các thuật toán liên quan có thể được tìm thấy trong nhiều sách biên dịch. Các thuật toán này được sử dụng bởi các chương trình unix như awk và grep.
Tuy nhiên, hầu hết các ngôn ngữ lập trình hiện đại (Perl, Python, Ruby, Java (và các ngôn ngữ dựa trên JVM), C #) không sử dụng phương pháp này. Họ sử dụng một cách tiếp cận quay lui đệ quy, trong đó biên dịch một biểu thức chính quy thành một cây hoặc một chuỗi các cấu trúc đại diện cho các phần phụ khác nhau của biểu thức chính quy. Hầu hết các cú pháp "biểu thức chính quy" hiện đại cung cấp các phản hồi nằm ngoài nhóm ngôn ngữ thông thường (chúng không có đại diện trong automata hữu hạn), có thể thực hiện được trong phương pháp quay lui đệ quy.
Việc tối ưu hóa thường mang lại một máy trạng thái hiệu quả hơn. Ví dụ: xem xét aaaab | aaaac | aaaad, một lập trình viên bình thường có thể thực hiện tìm kiếm đơn giản nhưng kém hiệu quả (so sánh ba chuỗi riêng biệt) ngay trong mười phút; nhưng nhận ra nó tương đương với aaaa [bcd], một tìm kiếm tốt hơn có thể được thực hiện bằng cách tìm kiếm bốn 'a' đầu tiên sau đó kiểm tra ký tự thứ 5 dựa vào [b, c, d]. Quá trình tối ưu hóa là một trong những công việc biên dịch tại nhà của tôi nhiều năm trước, vì vậy tôi cho rằng nó cũng có trong hầu hết các công cụ biểu thức chính quy hiện đại.
Mặt khác, các máy trạng thái có một số lợi thế khi chúng chấp nhận các chuỗi vì chúng sử dụng nhiều không gian hơn so với "triển khai tầm thường". Hãy xem xét một chương trình để bỏ dấu ngoặc kép trên các chuỗi SQL, nghĩa là: 1) bắt đầu và kết thúc bằng các dấu ngoặc đơn; 2) dấu ngoặc kép đơn được thoát bằng hai trích dẫn đơn liên tiếp. Vì vậy: đầu vào ['a' ''] sẽ mang lại đầu ra [a ']. Với một máy trạng thái, các dấu ngoặc kép đơn liên tiếp được xử lý bởi hai trạng thái. Hai trạng thái này phục vụ mục đích ghi nhớ lịch sử đầu vào sao cho mỗi ký tự đầu vào được xử lý chính xác chỉ một lần, như minh họa sau:
...
S1->'->S2
S1->*->S1, output *, * can be any other character
S2->'->S1, output '
S2->*->END, end the current string
Vì vậy, theo tôi, biểu thức chính quy có thể chậm hơn trong một số trường hợp tầm thường, nhưng thường nhanh hơn thuật toán tìm kiếm thủ công, do thực tế là việc tối ưu hóa có thể được thực hiện một cách đáng tin cậy bởi con người.
(Ngay cả trong các trường hợp tầm thường như tìm kiếm chuỗi, một công cụ thông minh có thể nhận ra đường dẫn duy nhất trong bản đồ trạng thái và giảm phần đó thành so sánh chuỗi đơn giản và tránh quản lý trạng thái.)
Một công cụ cụ thể từ khung / thư viện có thể chậm vì công cụ này thực hiện một loạt các thứ khác mà lập trình viên thường không cần. Ví dụ: lớp Regex trong .NET tạo ra một loạt các đối tượng bao gồm Khớp, Nhóm và Chụp.