कई पैटर्न grep करने के लिए xargs का उपयोग करना


12

मेरे पास एक फ़ाइल है जिसमें ऐसे शब्द हैं जिनके लिए मुझे grep चाहिए, प्रत्येक शब्द फ़ाइल में एक पंक्ति में है। मैं सोच रहा था कि मैं xargs के साथ ऐसा कर सकता हूं। मैं इस तरह से मैन पेज से उदाहरणों में चमकने में सक्षम हूं

find ./work -print0 | xargs -0 rm

यह है कि xargs अपने तर्कों के अंत में प्री-पाइप कमांड के आउटपुट को जोड़ता है। इसलिए यदि खोज वापस आ जाती है 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पारंपरिक यूनिक्स के रूप में सुझाव देता हूं grepऔर egrep"-f" विकल्प नहीं था। मेरा मानना ​​है कि GNU grepऔर egrepमें "-f" विकल्प होता है, इसलिए यदि आपकी फ़ाइल में नियमित अभिव्यक्ति है, तो आप GNU संस्करण का उपयोग करना चाहेंगे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.