Làm cách nào để tìm kiếm một chuỗi trong tệp PHP bằng cách sử dụng `grep`?


11

Tôi đang tìm kiếm một khai báo lớp trên một trang web có hàng trăm tệp PHP. Làm thế nào tôi có thể làm điều này trong thư mục hiện tại và các thư mục con bằng grep ?

Tôi đã thử cding vào thư mục và sau đó một cái gì đó như

grep -r 'class MyClass' *.php

Khi điều này chuyển sang siêu người dùng, bạn có thể muốn nói điều gì đó về những gì bạn muốn mà grep -rkhông cung cấp cho bạn.

Tôi bối rối - không phải bạn tự trả lời sao? kết quả của dòng đó là gì? bạn đang cố gắng để tối ưu hóa hơn nữa? xin vui lòng hình dung đọc câu hỏi này như một người khác, bởi vì nó khó hiểu và không rõ ràng.
meder omuraliev

@ther bình luận: Tuyên bố grep -r của anh ấy không đưa ra những gì anh ấy muốn, trừ khi tất cả các thư mục kết thúc bằng .php có lẽ không phải là trường hợp ...
David Oneill

Tôi không nhận được bất cứ điều gì cả. Tôi cho rằng nó không hoạt động vì tôi biết nó tìm thấy nó khi tôi đang ở trong thư mục chứa tệp này

Tôi tìm thấy các tập tin của may mắn. Khi tìm kiếm tệp trong thư mục có tệp PHP với dòng đó, nó tìm thấy nó (không cần -r). Nếu tôi CD vào thư mục gốc và thực hiện tìm kiếm với đệ quy -r thì nó không trả về bất cứ thứ gì.

Câu trả lời:


24

Bạn co thể thử

grep -r --include=*.php "search string" /path/to/dir

1
Công trình tuyệt vời. Tôi tiếp tục quên, nhưng may mắn thay, luôn có câu trả lời này một lần nữa để giúp tôi. :)
GolezTrol

@GolezTrol Vui mừng khi biết rằng :-)
rahul286

9

Tôi khuyên bạn nên sử dụng một cái gì đó như ctags hơn là làm với grep. Tuy nhiên, nếu bạn muốn, bạn có thể làm một cái gì đó như

 find <top level dir> -name \*.php | xargs grep "class MyClass"

Tất nhiên, điều này giả định rằng bạn chỉ có một khoảng trống giữa classmyClasscó thể không đúng. Thật dễ dàng để thay đổi biểu thức chính quy để tìm kiếm bất kỳ số lượng khoảng trắng nào.


4

Nếu bạn sử dụng -r, có lẽ bạn muốn tìm kiếm đệ quy chỉ thư mục hiện tại :

grep -r 'class MyClass' .

Lưu ý khoảng thời gian kết thúc ở trên.

Những gì bạn nói greplà bạn muốn nó tìm kiếm đệ quy mọi *.phptệp hoặc thư mục , nhưng bạn có thể không có bất kỳ thư mục nào kết thúc bằng một phần mở rộng .php. Trên đây là cách đơn giản nhất có thể để thực hiện tìm kiếm nhưng cũng bao gồm các tệp thuộc loại khác, đặc biệt có vấn đề khi bạn có các thư mục .svn ở mọi nơi. Nếu bạn không có nhiều loại tệp khác, thì ở trên nói chung là đủ và hoạt động tốt.

Hầu hết các hiện thân của grep không có cách chỉ định các phần mở rộng tệp có thể được tìm kiếm, vì vậy bạn thường sử dụng find kết hợp với nó:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;

-inamenói với một số phiên bản của grep mà bạn muốn thực hiện tìm kiếm tên tệp không phân biệt chữ hoa chữ thường, nhưng nhiều biến thể không phải của GNU không hỗ trợ nó, vì vậy bạn có thể sử dụng -namethay thế.

Các -exectùy chọn ở trên có tác dụng phụ của cách gọi grep cho mỗi tập tin, mà là khá tốn kém.

Các phiên bản khác của grep hỗ trợ một lệnh +tìm kiếm để nối các đối số lại với nhau để giảm số lần gọi của tệp thực thi:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;

Một cách thường xuyên được đề xuất để giảm các yêu cầu là sử dụng xargs sẽ bắn grep ít nhất có thể nhưng nhiều lần nếu cần:

find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"

xargsđủ thông minh để vượt qua grep đến số lượng đối số tối đa được hỗ trợ trên dòng lệnh, nhưng biến thể trên không xử lý tốt các ký tự nhất định như khoảng trắng. Ví dụ: 'file.php', tên tệp grep sẽ nhận 'the' làm đối số và 'file.php' làm đối số để cả hai sẽ không được tìm thấy. Thay vào đó chúng tôi sử dụng:

find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"

print0-0làm việc cùng nhau và sử dụng các đối số theo sau bởi một ký tự null để đối số được xác định hoàn toàn và rõ ràng.

Nếu bạn có nhiều hơn một khoảng trắng sau classhoặc một tab, bạn có thể muốn cho phép nhiều ký tự hơn bằng cách thay đổi biểu thức chính:class[ \t]*MyClass

Bài đăng này trên StackOverflow có các ví dụ khác và giải thích cách loại trừ các thư mục nhất định, như thư mục .svn.


Điều này tìm kiếm tất cả các tập tin. Ngoài ra các tệp không phải là tệp .php.
GolezTrol

Tôi đã cập nhật bài viết để bao gồm nhiều ví dụ khác.
Kaleb Pederson


1
grep -r 'class MyClass' *.php

sẽ tìm kiếm trong tất cả các thư mục có tên kết thúc bằng .php

grep -r 'class MyClass' . | grep .php

sẽ tìm kiếm lớp MyClass trong tất cả các tệp trong tất cả các thư mục con, sau đó chỉ trả về những tệp có .php trong đó.


1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; sẽ cung cấp cho bạn nội dung của dòng được tìm thấy cũng như đường dẫn đến tệp.


1

Trong trường hợp các tệp phù hợp có thể có tên tùy ý, bạn nên xem xét sử dụng -print0

tìm thấy . -type f -name '* .php' -print0 | xargs -0 grep 'lớp MyClass'


1
grep -rl 'class MyClass' . --include \*.php

Tôi chỉ hiển thị tên tệp

r là tái phát

. tìm kiếm trong thư mục hiện tại

- bao gồm giới hạn tên tệp mở rộng


1

Có lẽ bạn muốn độ nhạy cảm trường hợp và dung sai khoảng trắng và grep sẽ chấm dứt nếu nó không tìm thấy bất kỳ trường hợp nào của mẫu tệp mong muốn trong thư mục hiện tại. Nó cần phải biết bắt đầu từ đâu, vì nó đã được, và không có tệp nào khớp với nhau không tạo ra đường dẫn bắt đầu.

Nếu có ít nhất một tệp của tiện ích mở rộng mong muốn, thì bạn có thể sử dụng egrep -ir. findxargsthể hiện sức mạnh của họ với các thư mục phẳng (nhưng rất lớn) mà grep không thành công và các vòng loại bổ sung (ví dụ nếu bạn muốn tìm kiếm các tệp .inc, .php và php3). Nhưng nó mất khá nhiều sự tiện lợi và tốc độ trong trải nghiệm của tôi. Đối với khai báo lớp viết của con người, một vấn đề lớn sẽ là khoảng trắng. Vì vậy, sử dụng egrep thay vì grep. Ngoài ra LC_ALL = C cho tốc độ thêm. Để thuận tiện, tôi thường sử dụng:

LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"

-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.

[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname

Điều này vẫn có thể phù hợp với các nhận xét, chẳng hạn như // class myclass exists in file, nhưng tôi thấy chúng tương đối nhỏ và chúng có thể được lọc ra bằng... | fgrep -v '//'

Bạn cũng có thể bao gồm các mặt nạ tệp phức tạp hơn (ví dụ: để bắt hầu hết các tệp .inc và .php) trên mẫu tệp egrep như vậy:

egrep "pattern" *.[ip]*

Điều đó (với các tùy chọn đầu tiên) sẽ khá nhanh và chủ yếu giới hạn ở các tệp php.

HTH


0

Tôi biết nó nói sử dụng grep, nhưng sở thích cá nhân của tôi là sử dụng ack-grep:

ack-grep "class MyClass"

Điều này chạy đệ quy, liệt kê tên tệp mà nó tìm thấy kết quả, với số dòng cho nơi chúng được tìm thấy và các điểm nổi bật. Để nhắm mục tiêu cụ thể các tệp php, bạn có thể chạy:

ack-grep --type-set php:ext:php "path"

Các gói có rất nhiều tùy chọn; Tôi chắc chắn muốn giới thiệu nó (và duyệt trang người đàn ông liên quan của nó) để làm những việc ưa thích.

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.