Không có gì có nghĩa là trong một biểu thức chính quy?


16

Lệnh sau được sử dụng để tìm kiếm số điện thoại gồm 7 chữ số:

grep "[[:digit:]]\{3\}[ -]\?[[:digit:]]\{4\}" file

Không đại diện \?cho cái gì?

Câu trả lời:


21

Nó giống như ?trong nhiều công cụ biểu thức chính quy khác, và có nghĩa là "khớp 0 hoặc bất kỳ thứ gì xuất hiện trước nó".

Trong ví dụ của bạn, cái \?được áp dụng cho [ -], nghĩa là nó cố khớp một khoảng trắng hoặc dấu trừ, nhưng khoảng trắng hoặc dấu trừ là tùy chọn.

Vì vậy, bất kỳ trong số này sẽ phù hợp:

555 1234
555-1234
5551234

Lý do nó được viết \?thay vì ?là để tương thích ngược.

Phiên bản gốc đã grepsử dụng một loại biểu thức chính quy khác được gọi là "biểu thức chính quy cơ bản" trong đó ?chỉ có nghĩa là một dấu hỏi theo nghĩa đen.

Vì vậy, GNU grep có thể có chức năng 0 hoặc 1, họ đã thêm nó, nhưng phải sử dụng \?cú pháp để các tập lệnh được sử dụng ?vẫn hoạt động như mong đợi.

Lưu ý rằng grep có một -Etùy chọn làm cho nó sử dụng loại biểu thức chính quy phổ biến hơn, được gọi là "biểu thức chính quy mở rộng".

man 1 grep:

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression
          (ERE, see below).  (-E is specified by POSIX.)

   -G, --basic-regexp
          Interpret PATTERN as a basic regular expression (BRE, see below).
          This is the default.

...

Repetition
    A regular expression may be followed by one of several repetition operators:
    ?      The preceding item is optional and matched at most once.

...

    grep understands three different versions of regular expression syntax:
    “basic,” “extended” and “perl.”

...

Basic vs Extended Regular Expressions
    In basic regular expressions the meta-characters ?, +, {, |, (, and )
    lose their special meaning; instead use the backslashed versions
    \?, \+, \{, \|, \(, and \).

Thêm thông tin:


Các egreplệnh tương đương với grep -E. Đối với các phiên bản không phải là GNU grep, grepcó thể hoặc không thể chấp nhận -Etùy chọn này và egrepcó thể là một chương trình riêng biệt.
Keith Thompson

@KeithThndry, grep -Elà cách POSIX chính thức. egrepđã bị phản đối trong susv2 (1997) và bị xóa trong susv3 (2001) khỏi thông số kỹ thuật POSIX và Unix.
Stéphane Chazelas

1
\?là một GNUism mặc dù.
Stéphane Chazelas

8

Thật không may, cú pháp chính xác của biểu thức chính quy thay đổi đôi chút giữa các chương trình khác nhau: grep regexes không hoàn toàn giống với biểu thức sed, không giống hệt như biểu thức Emacs, không giống hệt như biểu thức C ++, và vì vậy trên. Để làm cho vấn đề tồi tệ hơn, ngay cả một công cụ "tiêu chuẩn" như grep cũng có thể thay đổi đôi chút giữa các hệ điều hành giống Unix khác nhau.

Trong một biểu thức chính tả, một số ký tự có ý nghĩa đặc biệt (chẳng hạn như dấu ngoặc vuông trong ví dụ của bạn) và trở lại nghĩa bình thường của chúng là ký tự chữ khi bạn "thoát" chúng bằng cách đặt dấu gạch chéo ngược trước chúng (vì vậy dấu ngoặc sẽ là Viết như \[). Những người khác làm việc theo cách khác và chỉ mang ý nghĩa đặc biệt khi thoát (ví dụ: n đơn giản chỉ là một chữ cái, nhưng \ n là một nguồn cấp dữ liệu). Và những điều này, một lần nữa, có thể khác nhau giữa các triển khai regex.

Trong hầu hết các triển khai regex, một dấu hỏi có nghĩa là mục trước đó là tùy chọn, trong khi dấu hỏi thoát (\?) Là dấu chấm hỏi theo nghĩa đen. Nhưng trong một số phương ngữ, đó là cách khác. Ví dụ của bạn có thể có ý nghĩa xung quanh, nhưng tôi nghi ngờ bạn có một trong những phương ngữ ở đâu? là một nghĩa đen và \? là biểu tượng tùy chọn. Vì vậy, regex của bạn có thể có nghĩa là "ba chữ số, theo sau là dấu cách hoặc dấu gạch ngang, theo sau là bốn chữ số".

(Một manh mối khác có thể được nhìn thấy trong các cấu trúc như \ {3 \}, rõ ràng có nghĩa là "chính xác 3 mục trước". Trong hầu hết các phương ngữ regex, điều này sẽ được viết {3} và \ {sẽ là một dấu ngoặc .)


6

Đây là một bản tóm tắt nhanh chóng về thông tin đã có trong các câu trả lời khác.

Trong grep, ?khớp với một ký tự dấu chấm hỏi theo nghĩa đen và \?biểu thị số không hoặc một lần xuất hiện của bất cứ điều gì xảy ra trước nó. Vì vậy, trong ví dụ trong câu hỏi của bạn, [ -]\?khớp với dấu cách hoặc dấu gạch nối hoặc không có gì.

Trong egrephoặc grep -E, đó là cách khác xung quanh; \?khớp với một dấu hỏi theo nghĩa đen và ?biểu thị số không hoặc một lần xuất hiện.

Điều này áp dụng cho GNU grep; các chi tiết cho việc triển khai grep không phải GNU có thể khác nhau đôi chút. Đặc biệt, grepvà trong egreplịch sử là hai chương trình riêng biệt và tôi không nghĩ rằng những cái cũ grep-Etùy chọn. POSIX không chỉ định grep -E, nhưng (tôi rất ngạc nhiên khi phát hiện ra) không đề cập đến egrep.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.