!rm`.*$
Với một regex duy nhất, Retina chạy trong chế độ Match. Điều này thường chỉ in số lượng các trận đấu, nhưng với !
chúng tôi định cấu hình nó để in các trận đấu thực tế thay thế (được phân tách bằng các đường dẫn).
Regex thực tế chỉ là .*$
. .*
khớp với bất kỳ dòng nào (có khả năng trống), bởi vì .
có thể khớp với bất kỳ ký tự nào ngoại trừ các dòng. Tôi sẽ đến $
trong một phút.
Làm thế nào để chúng tôi làm cho nó in các trận đấu ngược lại? Bằng cách sử dụng chế độ khớp từ phải sang trái của .NET, được kích hoạt bằng r
. Điều này có nghĩa là công cụ regex bắt đầu ở cuối chuỗi khi tìm kiếm kết quả khớp và hoạt động ngược.
Cuối cùng, m
làm cho $
khớp với kết thúc của một dòng thay vì kết thúc chuỗi. Tại sao chúng ta thậm chí cần điều đó? Vấn đề là .*
tạo ra các trận đấu không liên quan. Hãy xem xét sự thay thế regex
s/a*/$0x/
áp dụng cho đầu vào baaababaa
. Bạn sẽ nghĩ rằng điều này sẽ mang lại baaaxbaxbaax
, nhưng nó thực sự mang lại cho bạn baaaxxbaxxbaaxx
. Tại sao? Bởi vì sau khi khớp aaa
con trỏ của động cơ nằm giữa a
và b
. Bây giờ nó không thể khớp với bất kỳ a
s nào nữa , nhưng a*
cũng hài lòng với một chuỗi rỗng. Điều này có nghĩa, sau mỗi trận đấu bạn sẽ nhận được một trận đấu trống khác.
Chúng tôi không muốn điều đó ở đây, vì nó sẽ giới thiệu các dòng trống bổ sung, vì vậy chúng tôi loại bỏ các kết quả trùng khớp đó ( bắt đầu từ các dòng, do chế độ từ phải sang trái) bằng cách yêu cầu các kết quả khớp đó bao gồm phần cuối của dòng.
tac
là một chút lạ khi nói đến nguồn cấp dữ liệu. Nó biến đổia\nb\n
(trailfeed lineing) thànhb\na\n
vàa\nb
(không có trailfeed lineing) thànhba\n
. Đây có phải là cách mã của chúng tôi phải hành xử?