làm cách nào để sử dụng tùy chọn grep --include cho nhiều loại tệp?


98

Khi tôi muốn grep tất cả các tệp html trong một số thư mục, tôi thực hiện như sau

grep --include="*.html" pattern -R /some/path

hoạt động tốt. Vấn đề là làm thế nào để grep tất cả các file html, htm, php vào một thư mục nào đó?

Từ cú pháp Sử dụng grep --exclude / - include để không grep qua một số tệp nhất định , có vẻ như tôi có thể làm như sau

grep --include="*.{html,php,htm}" pattern -R /some/path

Nhưng thật đáng buồn, nó sẽ không hiệu quả với tôi.
FYI, phiên bản grep của tôi là 2.5.1.

Câu trả lời:


136

Bạn có thể sử dụng nhiều --includecờ. Điều này phù hợp với tôi:

grep -r --include=*.html --include=*.php --include=*.htm "pattern" /some/path/

Tuy nhiên, bạn có thể làm theo Deruijterđề xuất. Điều này phù hợp với tôi:

grep -r --include=*.{html,php,htm} "pattern" /some/path/

Đừng quên rằng bạn có thể sử dụng findxargscho những thứ này để:

find /some/path/ -name "*.htm*" -or -name "*.php" | xargs grep "pattern"

HTH


1
Tôi thấy vấn đề. Tôi đã sử dụng --include = " . {Html, php}" để ngăn trình bao mở rộng ' ' đồng thời ngăn trình bao mở rộng {html, php}. Có vẻ như dấu bằng trong --include = * có thể ngăn trình bao mở rộng '*'.
tianyapiaozi

xargs không thực sự thay thế; nhiều khi bạn cần tính năng này, bạn đang xử lý nhiều tệp hơn so với xargs sẽ xử lý.
James Moore

2
@JamesMoore: Hãy xem GNU Parallel . Nó thường có thể được sử dụng để thay thế cho xargs. Điều này cũng đáng để đọc nhanh. HTH.
Steve

3
@tianyapiaozi: Bạn đúng khi trích dẫn xung quanh việc mở rộng dấu ngoặc nhọn là vấn đề; Tuy nhiên, nếu không có phần trích dẫn, *nó vẫn phải chịu ảnh hưởng bởi một phần của mã thông báo mà nó được nhúng vào , nó chỉ xảy ra không khớp với bất kỳ thứ gì trong trường hợp này, bởi vì chỉ các tệp được đặt tên theo nghĩa đen--include=foo.html mới khớp. Để an toàn, hãy trích dẫn *(mà bạn có thể làm riêng với \*). Như một phần thưởng bổ sung, điều này làm cho nó rõ ràng hơn về mặt trực quan rằng không phải là lớp vỏ sẽ thực hiện việc đánh bóng trong trường hợp này.
mklement0

2
Đối với findgiải pháp: sử dụng -exec grep "pattern" {} +thay vì | xargs grep "pattern"mạnh mẽ hơn (ví dụ: xử lý các tên tệp có dấu cách) cũng như hiệu quả hơn.
mklement0

32

Sử dụng {html,php,htm}chỉ có thể làm việc như một mở rộng cú đúp , mà là một chuẩn (không phải POSIX-compliant) tính năng của bash, kshzsh.

  • Nói cách khác: đừng cố gắng sử dụng nó trong một tập lệnh nhắm mục tiêu /bin/sh- hãy sử dụng nhiều đối số rõ ràng--include trong trường hợp đó.

  • grepbản thân nó không hiểu {...}ký hiệu.

Để mở rộng dấu ngoặc nhọn được nhận dạng, nó phải là một mã thông báo (một phần của a) chưa được trích dẫn trên dòng lệnh.

Mở rộng dấu ngoặc nhọn mở rộng thành nhiều đối số , vì vậy trong trường hợp hiện tại, bạn grepsẽ thấy nhiều --include=... tùy chọn, giống như thể bạn đã chuyển chúng riêng lẻ.

Kết quả của việc mở rộng dấu ngoặc nhọn phụ thuộc vào việc mở rộng dấu nháy (mở rộng tên tệp) , có các cạm bẫy :

  • Mỗi đối số kết quả có thể được mở rộng hơn nữa thành các tên tệp phù hợp nếu nó xảy ra chứa các siêu ký tự hình cầu không được trích dẫn, chẳng hạn như *.
    Trong khi điều này là khó xảy ra với thẻ như --include=*.html(ví dụ, bạn phải có một tập tin theo nghĩa đen tên là một cái gì đó giống như --include=foo.htmlmột cái gì đó để phù hợp), nó là giá trị lưu giữ trong tâm trí nói chung.

  • Nếu nullglobtùy chọn shell được bật ( shopt -s nullglob) và không khớp với , đối số sẽ bị loại bỏ .

Do đó, để có một giải pháp hoàn toàn mạnh mẽ , hãy sử dụng những cách sau:

grep -R '--include=*.'{html,php,htm} pattern /some/path
  • '--include=*.'được coi là một nghĩa đen , do được trích dẫn đơn lẻ ; điều này ngăn cản việc giải thích một cách vô tình về *một nhân vật lấp lánh.

  • {html,php,htm}, - sự cần thiết - mở rộng dấu ngoặc nhọn [1] , mở rộng thành 3 đối số, do {...} trực tiếp theo sau '...'mã thông báo , bao gồm mã thông báo đó.

  • Do đó, sau khi loại bỏ trích dẫn bằng shell, 3 đối số theo nghĩa đen sau đây cuối cùng được chuyển đến grep :

    • --include=*.html
    • --include=*.php
    • --include=*.htm

[1] Chính xác hơn, chỉ những phần liên quan đến cú pháp của phần mở rộng dấu ngoặc nhọn mới phải được hủy trích dẫn, các phần tử danh sách vẫn có thể được trích dẫn riêng lẻ và phải được trích dẫn nếu chúng chứa các siêu ký tự hình cầu có thể dẫn đến nhấp nháy không mong muốn sau khi mở rộng dấu ngoặc nhọn; trong khi không cần thiết trong trường hợp này, phần trên có thể được viết là
'--include=*.'{'html','php','htm'}


1
Cám ơn rất nhiều vì bài viết. Bài viết tuyệt vời không chỉ trả lời câu hỏi mà còn dạy cho bạn điều gì đó mới! Điều này đặc biệt hữu ích cho những người trong chúng ta viết về thứ gì đó cần tuân thủ POSIX. Bất kỳ ai sử dụng Mac OS X nên xem ở đây!
sabalaba

@sabalaba: Tôi rất vui khi biết điều đó, nhưng cần phải nói rõ: mặc dù mở rộng dấu ngoặc nhọn không tuân thủ POSIX, nhưng nó hoạt động với bashbất kỳ nền tảng nào bashchạy trên đó.
mklement0

9

Thử xóa dấu ngoặc kép

grep --include=*.{html,php,htm} pattern -R /some/path

@tianyapiaozi Hãy thử grep --include=\*.{html,php,htm} pattern -R /some/path. Nó đã làm việc cho tôi.
Hyunjun Kim

4

cái này không hoạt động à?

  grep pattern  /some/path/*.{html,php,htm} 

Không hẳn vậy. Các tập tin có thể do cư trú trong thư mục con của thư mục con
tianyapiaozi

2

Thử cái này. -r sẽ thực hiện tìm kiếm đệ quy. -s sẽ ngăn chặn lỗi không tìm thấy tệp. -n sẽ hiển thị cho bạn số dòng của tệp nơi tìm thấy mẫu.

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}

Đây là câu trả lời tốt nhất đối với tôi đặc biệt và tôi nghĩ bạn có thể đặt -rsn thay vì -r -s -n (nhưng đó là nitpicking).
slim

Thông thường tôi sử dụng -rns . Để rõ ràng trong ví dụ, tôi phải đề cập đến -r -n -s :-) Rất vui vì nó đã giúp ích.
Pradeep

Tôi khuyên bạn nên thêm -Ivào bộ tiêu chuẩn. Nó bỏ qua các tệp nhị phân (hầu như không bao giờ được tìm kiếm) do đó tăng hiệu quả. Sau đó, chúng tôi grep -rIns ...chơi âm thanh độc đáo :)
đẫm máu

2

Nó hoạt động cho cùng một mục đích, nhưng không có --include tùy chọn. Nó cũng hoạt động trên grep 2.5.1.

grep -v -E ".*\.(html|htm|php)"

0

Sử dụng grepbằng findlệnh

find /some/path -name '*.html' -o -name '*.htm' -o -name '*.php' -type f 
 -exec grep PATTERN {} \+

Bạn có thể sử dụng -regex-regextypecác tùy chọn.

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.