Biểu thức chính quy hoạt động “ở mọi nơi”
(johndcook.com)- Biểu thức chính quy có tính năng và cú pháp được hỗ trợ khác nhau tùy từng triển khai, nên một mẫu dùng được trong một công cụ có thể thất bại hoặc cần chỉnh sửa trong môi trường khác
- Càng quen với những môi trường nhiều tính năng như Perl, bạn càng thường gặp vấn đề tương thích; nếu tính cả các máy tính không có quyền cài đặt, dùng tập con chung sẽ an toàn hơn
- Nếu định nghĩa “ở mọi nơi” theo cách nghiêm ngặt nhất, phạm vi sẽ hẹp đến mức chỉ còn literal, lớp ký tự
[…]và các ký tự đặc biệt cơ bản như. * ^ $ - Nếu dùng GNU
sed,awk,grepcùng với tùy chọn-Ecủasedvàgrep, tập tính năng chung có thể dùng được sẽ rộng hơn, nhưng trong tổ hợp nàyawknhìn chung trở thành mẫu số chung nhỏ nhất - Emacs cần dấu gạch chéo ngược cho
+? ( ) { } |, và ý nghĩa của\s,\Scũng khác, nên nếu muốn dùng cùng một biểu thức chính quy trên nhiều công cụ thì phải kiểm tra cả cú pháp ngoại lệ
Vì sao tính tương thích của biểu thức chính quy lại khó
- Bất tiện lớn nhất của biểu thức chính quy đến từ khác biệt giữa các triển khai
- Một tính năng được hỗ trợ trong công cụ này có thể hoàn toàn không có trong công cụ khác
- Ngay cả cùng một tính năng, cú pháp cũng có thể khác đôi chút
- Perl là một môi trường biểu thức chính quy có nhiều tính năng, nên những tính năng tưởng như hiển nhiên theo chuẩn Perl đôi khi lại thiếu trong các môi trường khác
- Cũng có thể dùng các lựa chọn thay thế giống Perl trong những công cụ khác, nhưng chúng không mang tính chuẩn, khiến bạn khó gửi mã có thể chạy ngay cho đồng nghiệp hoặc khách hàng
- Nếu tính cả tình huống phải làm việc trên máy tính không thể cài đặt phần mềm, cần một cách tiếp cận là tìm tập con các tính năng biểu thức chính quy hoạt động trên nhiều môi trường
- Càng định nghĩa “ở mọi nơi” nghiêm ngặt, số tính năng có thể dùng càng giảm
- Literal
- Lớp ký tự
[…] - Các ký tự đặc biệt
. * ^ $
Phạm vi chung trong sed, awk, grep và Emacs
- Nếu thu hẹp các công cụ mục tiêu còn
sed,awk,grepvà Emacs, có thể nới lỏng tiêu chí “ở mọi nơi” một chút - Khi dùng các phiên bản GNU của
sed,awk,grepvà áp dụng tùy chọn-Echosedvàgrep, danh sách tính năng chung sẽ rộng hơn- Tính năng biểu thức chính quy của ba công cụ này khá giống nhau
- Các tính năng của
awknhìn chung cũng được các công cụ khác hỗ trợ - Ngoại lệ là ranh giới từ: trong
awkdùng\<,\>, khác với\b,\B
- Emacs tương ứng với hầu hết tính năng của
awk, nhưng có khác biệt về cú pháp- Để
+ ? ( ) { } |có vai trò giống trongawk, cần đặt dấu gạch chéo ngược ở phía trước - Biểu thức tương ứng với
\s,\Scủaawktrong Emacs là\s-,\S-
- Để
- Trong Emacs,
\s,\Skhông phải là khoảng trắng/không phải khoảng trắng mà bắt đầu một lớp ký tự- Lớp
-nghĩa là khoảng trắng \s.là ký tự dấu câu\S.là ký tự không phải dấu câu
- Lớp
- Theo tiêu chí này, các tính năng có thể dùng gồm
.^,$[…],[^…]*\w,\W,\s,\S- Tham chiếu ngược từ
\1đến\9 \b,\B?,+- Lựa chọn thay thế
| - Số lần lặp
{n,m} - Nhóm bắt
(...)
- Tuy nhiên,
gawkhỗ trợ tham chiếu ngược trong chuỗi thay thế, nhưng không hỗ trợ tham chiếu ngược trong chính biểu thức chính quy look-aroundcó thể được xem là tính năng nâng cao, còn\dcó thể trông như tính năng cơ bản dành cho chữ số, nhưng không được hỗ trợ trong nhiều biến thể biểu thức chính quy
1 bình luận
Ý kiến trên Hacker News
Với Emacs thì đặc biệt vất vả, vì gần như phải đoán xem cần escape cái gì
Cũng có một lựa chọn thay thế tên là
rx[0], nhưng dùng thực tế thì không vui vẻ gìKhông chỉ cú pháp regex, mà cả ở bước sử dụng thực tế cũng thường phát sinh vấn đề về encoding và escape
Nhập regex trong shell thì phải escape cho đúng, còn trong Python thì phải kiểm tra xem có phải raw string hay không
Dù vậy, việc cách dùng regex trong phần lớn công cụ đã hội tụ trong một phạm vi tương đối giống nhau gần như là một phép màu thời hiện đại
[0]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Rx...
Các tình huống lồng nhiều quy tắc escape khác nhau cứ liên tục xảy ra
(và)được match theo nghĩa ký tự nguyên văn cũng hơi tiệnCó vẻ tác giả gần như chạm tới kết luận nhưng chưa nói hẳn ra: rốt cuộc POSIX basic regular expressions hoạt động ở mọi nơi
Tuy nhiên có kèm lưu ý rằng không phải ai cũng đã bắt kịp Single Unix Specification ấn bản 8, và trong ấn bản đó BRE đã thay đổi đôi chút
Nếu không có những lưu ý như vậy thì ngay từ đầu đã chẳng cần viết bài đó
Trước đây tôi từng viết một bài báo về việc tìm các regex match theo cùng một cách dưới cả hai kiểu ngữ nghĩa tham lam và ngữ nghĩa leftmost maximal
https://par.nsf.gov/servlets/purl/10534654
Tôi luôn khá khó tính trong việc phải làm rõ một công cụ chấp nhận ngôn ngữ regex nào, và nó match cái gì trong số chuỗi con bất kỳ, tiền tố, hậu tố, toàn bộ chuỗi, một dòng, hay chuỗi con trong một dòng
Có [những loại phổ biến hơn][1] ở đây, ngoài ra còn có PCRE và Python
Tôi đã mất một thời gian mới biết rằng một số dạng cũ thấy trong những nơi như grep [được đặc tả trong POSIX][2]
[1]: https://cppreference.com/cpp/regex#Regular_expression_gramma...
[2]: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd...
Muốn chia sẻ trang về regex của Russ Cox
Tôi thấy đây là tài liệu hay, đáng đọc
https://swtch.com/~rsc/regexp/
Vì những lý do như vậy, RFC 9485, I-Regexp: An Interoperable Regular Expression Format, rất quan trọng
https://datatracker.ietf.org/doc/html/rfc9485
Gói regexp trong thư viện chuẩn của Go không hỗ trợ backreference vì dùng engine RE2
Có thể dùng trong thay thế, nhưng không dùng được khi match
regexpkhông dùng re2, mà là một bản triển khai riêng của cùng ý tưởngSau khi gặp những bực bội tương tự với rule engine, template engine và các engine kiểu IFTTT, tôi đã tạo một thư viện Rust cho JSONLogic và cũng dùng các binding cho ngôn ngữ khác
https://github.com/GoPlasmatic/datalogic-rs
Trong tài liệu JSON Schema cũng có một tập con regex được khuyến nghị
https://json-schema.org/understanding-json-schema/reference/...