Đó là vì lý do lịch sử.
Regapi lần đầu tiên được giới thiệu trong Unix trong ed
tiện ích vào đầu những năm 70. Mặc dù ed
được dựa trên qed
mà thực hiện bởi các tác giả cùng hiểu regexp phức tạp hơn, ed
chỉ hiểu ^
, $
, [...]
, .
, *
và \
để thoát khỏi tất cả những điều trên.
Bây giờ, khi cần phải có nhiều toán tử phát sinh, một cách đã được tìm thấy để giới thiệu chúng mà không phá vỡ tính tương thích ngược. Nếu một kịch bản sử dụng để sử dụng các s
ed
lệnh như s/foo() {/foo (var) {/g
để thay thế tất cả các trường hợp foo() {
có foo(var) {
và bạn đã giới thiệu một (
hoặc {
điều hành, điều đó sẽ phá vỡ kịch bản đó.
Tuy nhiên, không có kịch bản nào có thể làm được s/foo\(\) {/foo\(var\) {/
, vì điều đó giống như s/foo() {/foo(var) {/
và không có lý do gì để thoát (
vì đó không phải là toán tử RE. Vì vậy, việc giới thiệu một toán tử mới \(
hoặc \{
toán tử không phá vỡ tính tương thích ngược vì rất khó có thể phá vỡ một tập lệnh hiện có bằng cú pháp cũ hơn.
Vì vậy, đó là những gì đã được thực hiện. Sau đó, \(...\)
được thêm vào ban đầu chỉ để s
ed
lệnh thực hiện những việc như s/foo\(.\)/\1bar/
và sau đó là grep '\(.\)\1'
(nhưng không phải là những thứ như \(xx\)*
).
Trong UnixV7 (1979, gần một thập kỷ sau), một dạng biểu thức chính quy mới đã được thêm vào trong phần mới egrep
và awk
các tiện ích gọi là biểu thức chính quy mở rộng (vì chúng là các công cụ mới, không có khả năng tương thích ngược bị phá vỡ). Cuối cùng, nó cung cấp chức năng có sẵn trong cổ đại của Ken Thompson qed
(toán tử thay thế |
, nhóm (..)*
) và thêm một vài toán tử thích +
và ?
(nhưng không có tính năng backref của các biểu thức chính quy cơ bản).
Sau đó, các BSD đã thêm \<
và \>
(vào cả BRE và ERE), và SysV chỉ thêm \{
và \}
vào BREs.
Mãi cho đến khi muộn hơn {
và }
được thêm vào ERE, bằng cách phá vỡ tính tương thích ngược. Không phải ai cũng thêm nó. Chẳng hạn, GNU awk
cho đến phiên bản 4.0.0 (2011) không hỗ trợ {
trừ khi bị ép buộc vào chế độ tuân thủ POSIX.
Khi GNU grep
được viết vào đầu những năm 90, nó đã thêm tất cả các ưu điểm từ cả BSD và SysV (như \<
, {
) và thay vì có hai cú pháp regrec và công cụ riêng cho BRE và ERE, đã triển khai cùng một toán tử trong cả hai, chỉ các đối tác BRE của (
, ?
, {
, +
phải được bắt đầu bằng một dấu gạch chéo (để tương thích với việc triển khai BRE khác). Đó là lý do tại sao bạn có thể làm .\+
trong GNU grep
(mặc dù đó không phải là POSIX hoặc được hỗ trợ bởi các triển khai khác) và bạn có thể làm (.)\1
trong GNU egrep
(mặc dù đó không phải là POSIX hoặc được hỗ trợ bởi nhiều triển khai khác bao gồm cả GNU awk
).
Thêm \x
toán tử không phải là cách duy nhất để thêm nhiều toán tử theo cách tương thích ngược. Ví dụ, perl
được sử dụng (?...)
. Điều đó vẫn tương thích ngược với ERE vì (?=...)
không hợp lệ trong ERE, tương tự như vậy .*?
. vim
đối với các nhà khai thác tương tự đã làm điều đó khác nhau bằng cách giới thiệu \@=
hoặc .\{-}
ví dụ.