birden çok desen grep için xargs kullanma


12

Her terim dosyada bir satır olmak, ben grep için terimleri olan bir dosya var. Bunu xargs ile yapabileceğimi düşünüyordum. Böyle man sayfasındaki örneklerden ayırabildiğim şey

find ./work -print0 | xargs -0 rm

xargs ön boru komutunun çıktısını argümanlarının sonuna eklemesidir. Eğer buluntu geri report.docdönerse, xargs inşa ederdi rm report.doc. Bu anlayış doğru mu?

Dosyamdaki değerlerin grep komutunun ortasında olmasını istediğimden, bir yer tutucu belirtmem gerekiyor. Oynarken, denedim {}, ama işe yaramadı:

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

Xargs doğru araç mı? Öyleyse, sözdizimi nedir?

Yanıtlar:


17

Evet, find ./work -print0 | xargs -0 rmböyle bir şey yürütecek rm ./work/a "work/b c" .... Sen ile kontrol edebilirsiniz echo, find ./work -print0 | xargs -0 echo rm(gerçi, uygun şekilde kaçırmak olacaktır boşluk hariç yürütülecek komutu yazdırır echoolduğunu göstermeyecektir).

Almak için xargsortada isimlerini koymak, eklemek gerekir -I[string]nerede, [string]kullandığınız ediyorum bu durumda, bağımsız değişkenle değiştirilmesi istediğiniz şeydir -I{}örn <strings.txt xargs -I{} grep {} directory/*.

Aslında kullanmak istediğiniz şey 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.)

Yani grep -Ff strings.txt subdirectory/*herhangi bir dizenin tüm oluşumlarını strings.txtbir değişmez olarak bulur , -Fseçeneği bırakırsanız dosyada normal ifadeleri kullanabilirsiniz. Aslında kullanabilirsiniz grep -F "$(<strings.txt)" directory/*. Pratik yapmak istiyorsanız find, özetin son iki örneğini kullanabilirsiniz. Yalnızca ilk düzey yerine yinelemeli arama yapmak istiyorsanız, özette de birkaç seçeneğiniz vardır.

Özet:

# 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

-lGerçek satırı görmeniz gerekmiyorsa, eşleşen her dosyanın adını almak için bu seçeneği kullanabilirsiniz :

-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

xargsfgrepeşleştirilecek dizeleriniz dosyası normal ifadeler değil, yalnızca dizeler içeriyorsa önereceğim en iyi araç olmayabilir .

fgrep -f strings.txt subdirectory/*

fgrepGeleneksel Unix olarak öneririm grepve egrep"-f" seçeneği yoktu. Ben GNU grepve egrep"-f" seçeneğine sahip olduğuna inanıyorum , bu nedenle dosyanızda düzenli ifadeler varsa, bir GNU sürümü kullanmak istersiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.