sử dụng xargs để grep nhiều mẫu


12

Tôi có một tệp có các thuật ngữ tôi muốn grep, với mỗi thuật ngữ là một dòng trong tệp. Tôi đã nghĩ rằng tôi có thể làm điều này với xargs. Những gì tôi có thể lượm lặt được từ các ví dụ từ trang người đàn ông như thế này

find ./work -print0 | xargs -0 rm

là xargs nối thêm đầu ra của lệnh pre-pipe vào cuối đối số của nó. Vì vậy, nếu tìm thấy trả về report.doc, thì xargs sẽ xây dựng rm report.doc. Sự hiểu biết này có đúng không?

Vì vậy, vì tôi muốn các giá trị trong tệp của mình nằm ở giữa lệnh grep, tôi cần chỉ định một trình giữ chỗ. Khi chơi xung quanh, tôi đã thử {}, nhưng nó không hoạt động:

$> cat strings.txt | xargs grep {} subdirectory/*
grep: string1: No such file or directory
grep: string2: No such file or directory

Xargs có phải là công cụ phù hợp? Nếu vậy, cú pháp là gì?

Câu trả lời:


17

Vâng, find ./work -print0 | xargs -0 rmsẽ thực hiện một cái gì đó như rm ./work/a "work/b c" .... Bạn có thể kiểm tra với echo, find ./work -print0 | xargs -0 echo rmsẽ in lệnh sẽ được thực thi (ngoại trừ khoảng trắng sẽ được thoát một cách thích hợp, mặc dù điều đó echosẽ không hiển thị điều đó).

Để xargsđặt tên ở giữa, bạn cần thêm -I[string], đâu [string]là thứ bạn muốn được thay thế bằng đối số, trong trường hợp này bạn sử dụng -I{}, vd <strings.txt xargs -I{} grep {} directory/*.

Những gì bạn thực sự muốn sử dụng là grep -F -f strings.txt:

-F, --fixed-strings
  Interpret PATTERN as a  list  of  fixed  strings,  separated  by
  newlines,  any  of  which is to be matched.  (-F is specified by
  POSIX.)
-f FILE, --file=FILE
  Obtain  patterns  from  FILE,  one  per  line.   The  empty file
  contains zero patterns, and therefore matches nothing.   (-f  is
  specified by POSIX.)

Vì vậy, grep -Ff strings.txt subdirectory/*sẽ tìm thấy tất cả các lần xuất hiện của bất kỳ chuỗi nào strings.txtdưới dạng bằng chữ, nếu bạn bỏ -Ftùy chọn, bạn có thể sử dụng các biểu thức thông thường trong tệp. Bạn thực sự có thể sử dụng grep -F "$(<strings.txt)" directory/*quá. Nếu bạn muốn thực hành find, bạn có thể sử dụng hai ví dụ cuối cùng trong bản tóm tắt. Nếu bạn muốn thực hiện tìm kiếm đệ quy thay vì chỉ cấp độ đầu tiên, bạn có một vài tùy chọn, cũng trong bản tóm tắt.

Tóm lược:

# grep for each string individually.
<strings.txt xargs -I{} grep {} directory/*

# grep once for everything
grep -Ff strings.txt subdirectory/*
grep -F "$(<strings.txt)" directory/*

# Same, using file
find subdirectory -maxdepth 1 -type f -exec grep -Ff strings.txt {} +
find subdirectory -maxdepth 1 -type f -print0 | xargs -0 grep -Ff strings.txt

# Recursively
grep -rFf strings.txt subdirectory
find subdirectory -type f -exec grep -Ff strings.txt {} +
find subdirectory -type f -print0 | xargs -0 grep -Ff strings.txt

Bạn có thể muốn sử dụng -ltùy chọn để chỉ lấy tên của từng tệp phù hợp nếu bạn không cần phải xem dòng thực tế:

-l, --files-with-matches
  Suppress  normal  output;  instead  print the name of each input
  file from which output would normally have  been  printed.   The
  scanning  will  stop  on  the  first match.  (-l is specified by
  POSIX.)

4

xargscó thể không phải là công cụ tốt nhất mà tôi đề xuất fgrepnếu tập tin khớp chuỗi của bạn chỉ chứa các chuỗi, không phải là biểu thức chính quy.

fgrep -f strings.txt subdirectory/*

Tôi đề nghị fgreplà Unix truyền thống grepegrepkhông có tùy chọn "-f". Tôi tin rằng GNU grepegrepcó tùy chọn "-f", vì vậy nếu tệp của bạn có các biểu thức chính quy trong đó, bạn sẽ muốn sử dụng phiên bản GNU.

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.