Grep कमांड के परिणामस्वरूप प्राप्त प्रत्येक पंक्ति को कैसे संसाधित करें


152

मेरे पास grep कमांड चलाने के बाद एक फ़ाइल से प्राप्त कई पंक्तियाँ हैं:

var=`grep xyz abc.txt`

मान लीजिए कि मुझे 10 लाइनें मिलीं, जिसके परिणामस्वरूप xyz शामिल हैं।

अब मुझे grep कमांड के परिणामस्वरूप मिली प्रत्येक पंक्ति को संसाधित करने की आवश्यकता है। मैं इसके लिए कैसे आगे बढ़ूं?


6
यहाँ कोई भी उत्तर grep -oइस प्रकार की चीज़ की शक्ति का उल्लेख नहीं करता है। -oझंडा वापस दे देंगे केवल उत्पादन की प्रति पंक्ति एक मैच के साथ, उस पाठ को मैचों। (यह संपूर्ण नहीं है, इसलिए echo aaa |grep 'a*'केवल आपको "आआ" देता है और तीन आंशिक मैचों "", "ए", और "आ" को छोड़ देता है)
एडम काट्ज

जवाबों:


269

आसान तरीकों में से एक आउटपुट को एक चर में संग्रहीत नहीं करना है, लेकिन थोड़ी देर / रीड लूप के साथ सीधे उस पर पुनरावृति करना है।

कुछ इस तरह:

grep xyz abc.txt | while read -r line ; do
    echo "Processing $line"
    # your code goes here
done

इस योजना में भिन्नताएँ हैं, यह इस बात पर निर्भर करता है कि आप क्या कर रहे हैं।

यदि आपको लूप के अंदर चरों को बदलने की आवश्यकता है (और उस परिवर्तन को इसके बाहर दिखाई दे रहा है), तो आप प्रक्रिया प्रतिस्थापन का उपयोग कर सकते हैं जैसा कि फेडोरक्वी के उत्तर में कहा गया है :

while read -r line ; do
    echo "Processing $line"
    # your code goes here
done < <(grep xyz abc.txt)

अगर xyz के साथ कोई रेखा नहीं है?
XYZ_Linux

तब कुछ भी नहीं होता है, लूप नहीं चलाया जाता है।
चटाई

13
इस पद्धति के साथ समस्या यह है कि (पाइप की वजह से) लूप के अंदर सब कुछ एक सब-उप में है, इसलिए लूप के दौरान लूप के बाहर परिभाषित चर सेट करने से लूप के बाद उनके मान उपलब्ध नहीं होते हैं!
डेविड डोरिया

3
@ डेविड: अपनी चिंता का समाधान करने के लिए एक विकल्प प्रदान किया। (फ़ेडोरक्वी ने पहले ही इसे संबोधित कर दिया था।)
मैट

उन आदेशों के लिए जिनकी आउटपुट की अंतिम पंक्ति एक नई रेखा के साथ समाप्त नहीं हुई है, आपको इसकी आवश्यकता होगी: while read p || [[ -n $p ]]; do ...( stackoverflow.com/questions/1521462/… ) से उधार लिया गया
ओहद श्नाइडर

21

आप निम्न while readलूप कर सकते हैं , grepजिसे तथाकथित प्रक्रिया प्रतिस्थापन के उपयोग से कमांड के परिणाम द्वारा खिलाया जाएगा :

while IFS= read -r result
do
    #whatever with value $result
done < <(grep "xyz" abc.txt)

इस तरह, आपको परिणाम को एक चर में संग्रहीत नहीं करना है, लेकिन लूप के आउटपुट को सीधे "इंजेक्ट" करना है।


BashFAQ / 001 में सिफारिशों के अनुसार IFS=और उपयोग पर ध्यान दें read -r: मैं एक फ़ाइल (डेटा स्ट्रीम, चर) लाइन-बाय-लाइन (और / या फ़ील्ड-बाय-फ़ील्ड) कैसे पढ़ सकता हूं? :

पढ़ने के लिए -r विकल्प बैकस्लैश व्याख्या को रोकता है (आमतौर पर बैकस्लैश न्यूलाइन जोड़ी के रूप में उपयोग किया जाता है, कई लाइनों पर जारी रखने के लिए या सीमांकक से बचने के लिए)। इस विकल्प के बिना, इनपुट में किसी भी तरह के बैकस्लैश को छोड़ दिया जाएगा। आपको रीड के साथ लगभग हमेशा -r विकल्प का उपयोग करना चाहिए।

IFS के ऊपर के परिदृश्य में = व्हाट्सएप को अग्रणी और अनुगामी बनाने से रोकता है। यदि आप यह प्रभाव चाहते हैं तो इसे हटा दें।

प्रक्रिया प्रतिस्थापन के संबंध में, इसे हैश पेज में समझाया गया है :

प्रक्रिया प्रतिस्थापन एक पुनर्निर्देशन का एक रूप है जहां एक प्रक्रिया का इनपुट या आउटपुट (कुछ अनुक्रम के आदेश) एक अस्थायी फ़ाइल के रूप में दिखाई देते हैं।


ठीक है, मैंने forसंस्करण निकाला । पर एक पाश करने की कोशिश की "${$(grep xyz abc.txt)[@]}"के रूप में stackoverflow.com/a/14588210/1983854 लेकिन नहीं कर सके। इसलिए मैं सिर्फ पहला संस्करण छोड़ता हूं।
फेडोरक्वी 'एसओ ने

1
आप कमांड प्रतिस्थापन के लिए पैरामीटर विस्तार लागू नहीं कर सकते हैं (जब तक आप उपयोग नहीं कर रहे हैं zsh, जहां उस तरह का घोंसला शायद काम करता है)।
चेपनर

इस मुहावरे के साथ एक संभावित समस्या यह है कि अगर लूप के अंदर कुछ भी मानक इनपुट से पढ़ने की कोशिश करता है, तो यह फ़ाइल का हिस्सा होगा। इस संभावना से बचने के लिए, मैं फ़ाइल डिस्क्रिप्टर 3 के माध्यम से फ़ाइल को भेजने की बजाय स्टडिन को भेजना पसंद करता हूं। बस का उपयोग करें while IFS= read -r result <&3औरdone 3< <(grep ...
गॉर्डन डेविसन

8

मैं यहाँ grep + कुछ और के बजाय awk का उपयोग करने का सुझाव दूंगा।

awk '$0~/xyz/{ //your code goes here}' abc.txt


1
आप पूर्ण मिली लाइन का संदर्भ कैसे देंगे //your code goes here?
user857990

2
@ user857990 पूरी लाइन को AWK में $ 0 के रूप में दर्शाया गया है।
जूलियन ग्रेनियर

2

बिना किसी लाइन के - बिना बफर वाले grep विकल्प के साथ:

your_command | grep --line-buffered "your search"

वास्तविक जीवन में एक सिम्फनी PHP फ्रेमवर्क राउटर डिबग कमांड के साथ छूट, सभी "एपीआई" संबंधित मार्गों को प्राप्त करने के लिए:

php bin/console d:r | grep --line-buffered "api"

एकमात्र समाधान जो आपके काम करता है अगर आपका_कम लंबे समय से चल रहा है (जैसे कि tail -f some.log, मेरे मामले में) ...
इज़काता

0

अक्सर प्रसंस्करण का क्रम मायने नहीं रखता है। इस स्थिति के लिए GNU समानांतर बनाया गया है:

grep xyz abc.txt | parallel echo do stuff to {}

यदि आप प्रसंस्करण अधिक पसंद कर रहे हैं:

grep xyz abc.txt | myprogram_reading_from_stdin

और myprogramधीमा है तो आप चला सकते हैं:

grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin

0

थोड़ी देर / पढ़ने वाले लूप के साथ grep परिणामों पर Iterate करें। पसंद:

grep pattern filename.txt | while read -r line ; do
    echo "Matched Line:  $line"
    # your code goes here
done

0

एक-लाइनर की तलाश करने वालों के लिए:

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.