ใช้ xargs เพื่อ grep หลายรูปแบบ


12

ฉันมีไฟล์ที่มีคำที่ฉันต้องการ grep โดยแต่ละคำจะเป็นหนึ่งบรรทัดในไฟล์ ฉันคิดว่าฉันสามารถทำได้ด้วย xargs สิ่งที่ฉันสามารถรวบรวมได้จากตัวอย่างจากหน้าคนแบบนี้

find ./work -print0 | xargs -0 rm

คือ xargs ผนวกเอาต์พุตของคำสั่ง pre-pipe ต่อท้ายอาร์กิวเมนต์ ดังนั้นหากพบว่ากลับมาแล้วจะสร้างreport.doc xargs rm report.docความเข้าใจนี้ถูกต้องหรือไม่

ดังนั้นเนื่องจากฉันต้องการค่าในไฟล์ของฉันที่จะอยู่ตรงกลางของคำสั่ง grep ฉันต้องระบุตัวแทน ในการเล่นฉันพยายาม{}แต่มันไม่ทำงาน:

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

xargs เป็นเครื่องมือที่ใช่หรือไม่ ถ้าใช่ไวยากรณ์คืออะไร?

คำตอบ:


17

ใช่จะดำเนินการบางอย่างเช่นfind ./work -print0 | xargs -0 rm rm ./work/a "work/b c" ...คุณสามารถตรวจสอบกับecho, find ./work -print0 | xargs -0 echo rmจะพิมพ์คำสั่งที่จะดำเนินการ (ยกเว้นพื้นที่สีขาวจะหนีเหมาะสมแม้echoจะไม่ได้แสดงให้เห็นว่า)

ที่จะได้รับxargsการใส่ชื่อที่อยู่ตรงกลางคุณจำเป็นต้องเพิ่ม-I[string]ซึ่ง[string]คือสิ่งที่คุณต้องการที่จะถูกแทนที่ด้วยการโต้แย้งในกรณีนี้คุณต้องการใช้เช่น-I{}<strings.txt xargs -I{} grep {} directory/*

สิ่งที่คุณต้องการใช้คือ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.)

ดังนั้นgrep -Ff strings.txt subdirectory/*จะพบการเกิดขึ้นของสตริงใด ๆ ในstrings.txtรูปแบบตัวอักษรหากคุณวางตัว-Fเลือกคุณสามารถใช้การแสดงออกปกติในไฟล์ คุณสามารถใช้จริงได้grep -F "$(<strings.txt)" directory/*เช่นกัน หากคุณต้องการฝึกฝนfindคุณสามารถใช้สองตัวอย่างสุดท้ายในการสรุป หากคุณต้องการค้นหาแบบเรียกซ้ำโดยไม่ต้องค้นหาระดับแรกคุณจะมีตัวเลือกไม่กี่ตัวเลือกเช่นกันในบทสรุป

สรุป:

# 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

คุณอาจต้องการใช้-lตัวเลือกเพื่อรับชื่อของแต่ละไฟล์ที่ตรงกันหากคุณไม่ต้องการเห็นบรรทัดจริง:

-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

xargsอาจไม่ใช่เครื่องมือที่ดีที่สุดที่ฉันแนะนำfgrepถ้าไฟล์ของสตริงที่จะจับคู่ของคุณมีสตริงเท่านั้นไม่ใช่นิพจน์ทั่วไป

fgrep -f strings.txt subdirectory/*

ฉันแนะนำfgrepเป็น Unix แบบดั้งเดิมgrepและegrepไม่มีตัวเลือก "-f" ฉันเชื่อว่า GNU grepและegrepมีตัวเลือก "-f" ดังนั้นหากไฟล์ของคุณมีการแสดงออกปกติคุณจะต้องการใช้เวอร์ชัน GNU

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.