Làm thế nào tôi có thể grep cho điều này hoặc điều đó (2 điều) trong một tập tin?


38

Tôi có một tập tin có "rồi" và "có".

tôi có thể

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

và tôi có thể

$ grep "there " x.x
If there is no blob none some will be created

Làm thế nào tôi có thể tìm kiếm cả hai trong một hoạt động? Tôi đã thử

$ grep (then|there) x.x

-bash: lỗi cú pháp gần mã thông báo bất ngờ `('

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

Câu trả lời:


54

Bạn cần đặt biểu thức trong dấu ngoặc kép. Lỗi bạn đang nhận là kết quả của việc bash diễn giải thành (một ký tự đặc biệt.

Ngoài ra, bạn cần nói với grep để sử dụng các biểu thức chính quy mở rộng.

$ grep -E '(then|there)' x.x

Nếu không có biểu thức thông thường kéo dài, bạn phải thoát khỏi |, (). Lưu ý rằng chúng tôi sử dụng dấu ngoặc đơn ở đây. Bash xử lý dấu gạch chéo ngược trong dấu ngoặc kép đặc biệt.

$ grep '\(then\|there\)' x.x

Nhóm này không cần thiết trong trường hợp này.

$ grep 'then\|there' x.x

Nó sẽ là cần thiết cho một cái gì đó như thế này:

$ grep 'the\(n\|re\)' x.x

3
Xem thêm grep $'then\nthere'grep -e then -e there. Lưu ý rằng \|không phải là tiêu chuẩn trong BREs. Phần còn lại là. Bash xử lý backslashes đặc biệt trong dấu ngoặc kép chỉ trước ", $, \ , `và xuống dòng.
Stéphane Chazelas

1
Mục đích của là x.xgì?
alex

7

Chỉ cần một phụ lục nhanh, hầu hết các hương vị đều có một lệnh gọi là egrep chỉ là grep với -E. Cá nhân tôi thích tốt hơn nhiều để gõ

egrep "i(Pod|Pad|Phone)" access.log

Hơn để sử dụng grep -E


2

Các tài liệu được ghi lại dưới phần R EX RÀNG THƯỜNG XUYÊN trong trang người đàn ông (hoặc ít nhất là của tôi) thực sự dành cho các biểu thức mở rộng ;

grep hiểu ba phiên bản khác nhau của cú pháp biểu thức chính quy: Trong các triển khai khác, các biểu thức chính quy cơ bản ít mạnh hơn. Mô tả sau đây áp dụng cho các biểu thức chính quy mở rộng; sự khác biệt cho các biểu thức chính quy cơ bản được tóm tắt sau đó.

Nhưng grep không sử dụng chúng theo mặc định - bạn cần -Echuyển đổi:

grep "(then|there)" x.x

Bởi vì (từ trang người đàn ông một lần nữa):

Biểu thức cơ bản và mở rộng

Trong các biểu thức chính quy cơ bản, các ký tự meta ?, +, {, |, (Và) mất ý nghĩa đặc biệt của chúng; thay vào đó, hãy sử dụng các phiên bản gạch chéo ngược \?, +, {, \ |, (, và).

Vì vậy, bạn cũng có thể sử dụng:

grep "then\|there" x.x

Vì các dấu ngoặc đơn là thừa trong trường hợp này.


0

Sự đơn giản thanh lịch của Bash dường như bị lạc trong trang người đàn ông khổng lồ của nó.

Ngoài các giải pháp tuyệt vời ở trên, tôi nghĩ tôi sẽ cố gắng cung cấp cho bạn một bảng cheat về cách bash phân tích cú pháp và diễn giải các câu lệnh . Sau đó, sử dụng lộ trình này tôi sẽ phân tích các ví dụ được trình bày bởi người hỏi để giúp bạn hiểu rõ hơn lý do tại sao chúng không hoạt động như dự định.


Lưu ý: Dòng script Shell được sử dụng trực tiếp. Các dòng đầu vào được gõ được mở rộng lịch sử đầu tiên.

Mỗi dòng bash được mã hóa đầu tiên hoặc nói cách khác được cắt thành những gì được gọi là mã thông báo . (Mã thông báo xảy ra trước tất cả các bản mở rộng khác, bao gồm dấu ngoặc, dấu ngã, tham số, lệnh, số học, quy trình, tách từ và mở rộng tên tệp.)

Mã thông báo ở đây có nghĩa là một phần của dòng đầu vào được phân tách (được phân tách) bởi một trong các ký tự meta đặc biệt sau:

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bash sử dụng nhiều ký tự đặc biệt khác nhưng chỉ 10 cái này tạo ra các mã thông báo ban đầu.

Tuy nhiên vì đôi khi các ký tự meta này đôi khi cũng phải được sử dụng trong mã thông báo, cần có một cách để loại bỏ ý nghĩa đặc biệt của chúng. Điều này được gọi là thoát. Thoát được thực hiện bằng cách trích dẫn một chuỗi một hoặc nhiều ký tự, (ví dụ 'xx..', "xx.."), hoặc bằng cách đặt trước một nhân vật cá nhân với một back-slash, (ví dụ \x). (Nó phức tạp hơn một chút so với điều này bởi vì các trích dẫn cũng cần được trích dẫn, và vì các trích dẫn kép không trích dẫn mọi thứ, nhưng việc đơn giản hóa này sẽ làm ngay bây giờ.)

Đừng nhầm lẫn trích dẫn bash với ý tưởng trích dẫn một chuỗi văn bản, như trong các ngôn ngữ khác. Những gì ở giữa các dấu ngoặc kép trong bash không phải là các chuỗi, mà là các phần của dòng đầu vào có các ký tự meta được thoát để chúng không phân định mã thông báo.

Lưu ý, có một sự khác biệt quan trọng giữa ', và ", nhưng đó là cho một ngày khác.

Các ký tự meta không được giải mã còn lại sau đó trở thành dấu tách mã thông báo.

Ví dụ,

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

Trong ví dụ đầu tiên, có hai mã thông báo được tạo bởi một dấu phân cách không gian: echoxyz.

Tương tự như vậy trong ví dụ thứ 2.

Trong ví dụ thứ ba dấu chấm phẩy được bỏ trốn, do đó, có 4 thẻ được sản xuất bởi một dấu phân cách không gian, echo, x;, echo, và y. Mã thông báo đầu tiên sau đó được chạy dưới dạng lệnh và lấy ba mã thông báo tiếp theo làm đầu vào. Lưu ý thứ 2 echokhông được thực thi.


Điều quan trọng cần nhớ là vẻ bề ngoài đầu tiên bash cho các ký tự thoát ( ', "\), và sau đó tìm kiếm delimiters meta-nhân vật không thoát ra, theo thứ tự đó.

Nếu không thoát thì 10 ký tự đặc biệt này đóng vai trò là tokendấu phân cách. Một số trong số chúng cũng có ý nghĩa bổ sung, nhưng trước hết, chúng là các dấu phân cách mã thông báo.


Những gì grep mong đợi

Trong ví dụ trên grep cần những thẻ, grep, string, filename.

Câu hỏi đầu tiên của câu hỏi là:

$ grep (sau đó | có) xx

Trong trường hợp này (, )|là nhân vật siêu thoát và để phục vụ để phân chia các đầu vào vào các thẻ: grep, (, then, |, there, ), và x.x. grep muốn nhìn thấy grep, then|therex.x.

Lần thử thứ hai của câu hỏi là:

grep "(sau đó | có)" xx

Đây tokenizes vào grep, (then|there), x.x. Bạn có thể thấy điều này nếu bạn trao đổi grep cho echo:

echo "(sau đó | có)" xx
(sau đó | có) xx

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.