Tài liệu tham khảo có thẩm quyền về các vấn đề thực tế đằng sau việc triển khai các công cụ regex là một loạt ba bài đăng trên blog của Russ Cox . Như được mô tả ở đó, vì phản hồi làm cho ngôn ngữ của bạn không đều đặn, chúng được thực hiện bằng cách sử dụng quay lui .
Lookahead và lookbehind, giống như nhiều tính năng của công cụ khớp mẫu regex, không hoàn toàn phù hợp với mô hình quyết định liệu một chuỗi có phải là thành viên của ngôn ngữ hay không. Thay vì với các biểu thức chính, chúng ta thường tìm kiếm các chuỗi con trong một chuỗi lớn hơn. "Khớp" là các chuỗi con là thành viên của ngôn ngữ và giá trị trả về là điểm bắt đầu và điểm kết thúc của chuỗi con trong chuỗi lớn hơn.
Điểm của lookahead và lookbehind không phải là quá nhiều để giới thiệu khả năng khớp các ngôn ngữ không thông thường, mà là điều chỉnh nơi động cơ báo cáo điểm bắt đầu và điểm kết thúc của chuỗi con phù hợp.
Tôi đang dựa vào mô tả tại http://www.THER-expressions.info/lookaround.html . Các công cụ regex hỗ trợ tính năng này (Perl, TCL, Python, Ruby, ...) dường như đều dựa trên quay lui (nghĩa là chúng hỗ trợ một bộ ngôn ngữ lớn hơn nhiều so với chỉ các ngôn ngữ thông thường). Họ dường như đang thực hiện tính năng này như một phần mở rộng tương đối "đơn giản" của quay lui, thay vì cố gắng xây dựng automata hữu hạn thực sự để thực hiện nhiệm vụ.
Nhìn tích cực
Cú pháp cho cái nhìn tích cực là (?=
regex)
. Vì vậy, ví dụ chỉ q(?=u)
khớp q
nếu nó được theo sau u
, nhưng không khớp với u
. Tôi tưởng tượng họ thực hiện điều này với một biến thể về quay lui. Tạo một FSM cho biểu thức trước cái nhìn tích cực. Khi phù hợp, hãy nhớ nơi nó kết thúc và bắt đầu một FSM mới thể hiện biểu hiện bên trong diện mạo tích cực. Nếu trận đấu đó thì bạn có một "trận đấu", nhưng trận đấu "kết thúc" ngay trước vị trí bắt đầu trận đấu nhìn tích cực.
Phần duy nhất của điều này sẽ khó mà không quay lại là bạn cần nhớ điểm trong đầu vào nơi giao diện bắt đầu và di chuyển băng đầu vào của bạn trở lại vị trí này sau khi bạn hoàn thành khớp.
Cái nhìn tiêu cực
Cú pháp cho cái nhìn tiêu cực là (?!
regex)
. Vì vậy, ví dụ chỉ q(?!u)
khớp q
nếu nó không được theo sau u
. Điều này có thể là q
theo sau bởi một số ký tự khác hoặc một q
ở cuối chuỗi. Tôi tưởng tượng điều này được thực hiện bằng cách tạo NFA cho biểu thức nhìn, sau đó chỉ thành công nếu NFA không khớp với chuỗi tiếp theo.
Nếu bạn muốn làm điều đó mà không cần dựa vào việc quay lại, bạn có thể phủ nhận NFA của biểu thức nhìn, sau đó xử lý nó giống như cách bạn đối xử với cái nhìn tích cực.
Nhìn tích cực
(?<=
)
(?=q)u
u
q
q
nnn
Bạn có thể thực hiện điều này mà không cần quay lại bằng cách lấy giao điểm của "chuỗi kết thúc bằng regex " với bất kỳ phần nào của biểu thức chính xuất hiện trước toán tử lookbehind. Điều này sẽ rất khó khăn, bởi vì regex của lookbehind có thể cần nhìn lại hơn so với đầu hiện tại của đầu vào.
Cái nhìn tiêu cực
Cú pháp cho cái nhìn tiêu cực là (?<!
regex)
. Vì vậy, ví dụ, (?<!q)u
khớp u
, nhưng chỉ khi nó không đi trước q
. Vì vậy, nó sẽ phù hợp với u
trong umbrella
và u
trong doubt
, nhưng không phải u
trong quick
. Một lần nữa, điều này dường như được thực hiện bằng cách tính toán độ dài của regex , sao lưu nhiều ký tự đó, thử nghiệm cho trận đấu với regex , nhưng bây giờ thất bại toàn bộ trận đấu nếu giao diện khớp.
Bạn có thể thực hiện điều này mà không cần quay lại bằng cách lấy sự phủ định của regex và sau đó thực hiện tương tự như bạn sẽ làm cho cái nhìn tích cực.