Làm cách nào để tôi thực hiện xargs grep trên đầu ra grep có khoảng trắng?


8

Tôi đang tìm kiếm các tệp dựa trên biểu thức chính quy và sau đó tôi đang cố gắng tìm kiếm các tệp đó cho nội dung. Vì vậy, ví dụ, tôi có một cái gì đó như

#Find all C++ files that match a certain pattern and then search them
find . -name "*.cpp" | grep "<name regex>" | xargs grep "<content regex>"

Vấn đề tôi gặp phải là một số đường dẫn có khoảng trống trong đó, gây nhầm lẫn xargs. Tôi biết rằng nếu tôi chỉ sử dụng find, tôi có thể sử dụng -print0đối số (cùng với -0đối số trên xargs) để giữ xargs không coi các khoảng trắng là dấu phân cách. Có cái gì đó tương tự với grep?

Hay tôi đang tiếp cận vấn đề này một cách sai lầm hoàn toàn? Ngây thơ, findđể grepcho xargs grepcó ý nghĩa đối với tôi, nhưng tôi mở cửa cho các phương pháp khác mà mang lại kết quả tương tự.


2
bạn có thể định vị các đối số xargsbằng cách sử dụng -itham số, a la cat sample.txt | grep "pat t ern" | xargs -i grep "{}"- dấu ngoặc nhọn cho nó biết vị trí của đối số. Hướng dẫn cho tôi biết rằng -ikhông được ủng hộ -Ivì vậy có lẽ cũng đáng để xem qua.
dougBTV

Câu trả lời:


5

Sử dụng một cái gì đó như thế này có lẽ (nếu gnu grep).

grep -r 'content pattern' --include==*.cpp

người đàn ông grep

--include = GLOB Chỉ tìm kiếm các tệp có tên cơ sở khớp với GLOB (sử dụng khớp ký tự đại diện như được mô tả trong --exclude)

Cũng xem các tùy chọn cho dấu phân cách null.

-Z, --null Xuất ra một byte 0 (ký tự ASCII NUL) thay vì ký tự thường theo sau tên tệp. Ví dụ, grep -lZ xuất ra một byte bằng 0 sau mỗi tên tệp thay vì dòng mới thông thường. Tùy chọn này làm cho đầu ra không rõ ràng, ngay cả khi có tên tệp chứa các ký tự bất thường như dòng mới. Tùy chọn này có thể được sử dụng với các lệnh như find -print0, perl -0, sort -z và xargs -0 để xử lý tên tệp tùy ý, ngay cả những lệnh chứa ký tự dòng mới.

-z, --null-data Xử lý đầu vào dưới dạng một tập hợp các dòng, mỗi dòng được kết thúc bằng một byte 0 (ký tự ASCII NUL) thay vì một dòng mới. Giống như tùy chọn -Z hoặc --null, tùy chọn này có thể được sử dụng với các lệnh như sort -z để xử lý tên tệp tùy ý.


Lưu ý rằng grep -r include='*.cpp'là một glob vỏ - và như vậy là tính năng liên kết w / find . -name '*.cpp' -exec grep -e 'content_pattern' -- {} \;không w /find . -name '*.cpp' | grep 'name_pattern' | xargs grep 'content_pattern'
mikeserv

4

Nếu bạn phải nhảy qua rất nhiều vòng, thì dù sao thì hiệu quả của xargs cũng bị mất. Đây là một công việc thô sơ xung quanh:

find . -iname "*.cpp" | grep "<pattern>" | while read -r x; do grep exa "$x"; done

Mỗi lần tôi gặp vấn đề với khoảng trắng trong tên tệp, câu trả lời là dấu ngoặc kép trên một biến.


Điều này chạy grep bên trong của vòng lặp duy nhất cho mỗi dòng được tìm thấy bởi grep bên ngoài. Đó là rất nhiều chi phí.
Adam Katz

3

Sử dụng findđể thực hiện tất cả các lọc tên tệp. Thay vì

find . -name "*.cpp" | grep "foo" | xargs grep 

làm

find . -name "*.cpp" -name "*foo*" -print0 | xargs -0 grep 

Nếu bạn muốn làm một cái gì đó phức tạp hơn một chút, như

find . -name "*.cpp" | egrep "foo|bar" | xargs grep 

bạn có thể làm

find . -name "*.cpp" "(" -name "*foo*" -o -name "*bar*" ")" -print0 | xargs -0 grep 

Lưu ý rằng chúng nên hoạt động ngay cả đối với các tệp có dòng mới trong tên của chúng.

Và, nếu bạn cần sức mạnh của các biểu thức chính quy đầy đủ, bạn có thể sử dụng -regex.


2

Điều này sẽ hoạt động ngay cả khi không có các công cụ GNU:

#Find all C++ files that match a certain pattern and then search them
find . -name "*.cpp"  | grep "<name regex>" | perl -pe 's/\n/\0/' \
  | xargs -0 grep "<content regex>"

Cuộc perlgọi thay thế ngắt dòng bằng ký tự null, điều này sẽ cho phép xargs -0diễn giải đầu vào trên cơ sở từng dòng thay vì trên cơ sở mỗi khoảng trắng.

Sử dụng GNU, bạn có thể xóa perlcuộc gọi và thay đổi xargs -0 …thànhxargs -d "\n" …

Không có perlhoặc GNU? Hãy thử awk '{printf "%s%c", $0, 0}'thay thế.


1
Điều này có thể không làm đúng nếu một số tên tệp bao gồm các dòng mới (một sự xuất hiện khá bất thường, chắc chắn, nhưng không phải là không thể).
dhag 19/03/2015

@dhag có một điểm hợp lệ liên quan xargs -d "\n". Đó là một sự cố rất bất thường, nhưng nếu bạn không kiểm soát được dữ liệu và lo lắng về việc đó có phải là rủi ro bảo mật hay không, hãy cẩn thận với những kỳ vọng đầu ra.
Adam Katz
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.