किसी फ़ाइल में टेक्स्ट के लिए grep कैसे करें और उस पैराग्राफ को प्रदर्शित करें जिसमें टेक्स्ट है?


24

नीचे फ़ाइल में पाठ है:

Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

मुझे "42B" के लिए grep चाहिए और उपरोक्त पाठ से आउटपुट प्राप्त करना होगा जैसे:

Pseudo name=Apple
Code=42B
state=fault

क्या किसी को इस पर विचार करना है कि इसे कैसे प्राप्त किया जाए grep/ awk/ sed?


आपने इस प्रश्न को केवल "grep" के साथ टैग किया है। क्या आप केवल "grep" समाधान खोज रहे हैं? प्रश्न में आप awk और sed भी निर्दिष्ट करते हैं। क्या हम उन टैग्स को जोड़ सकते हैं? जब मैंने कल रात प्रश्न संपादित किया तो मुझे आपके इरादे का यकीन नहीं था।
SLM

जवाबों:


38

साथ में awk

awk -v RS='' '/42B/' file

RS=एक इनपुट लाइन विभाजक को नई लाइन से रिक्त लाइनों में बदलता है। यदि किसी रिकॉर्ड में किसी भी फ़ील्ड में रिकॉर्ड /42B/प्रिंट होता है ।

''(नल स्ट्रिंग) POSIX के अनुसार रिक्त लाइनों का प्रतिनिधित्व करने के लिए उपयोग किया जाने वाला एक जादू मूल्य है :

यदि आरएस शून्य है, तो रिकॉर्ड <newline>एक या एक से अधिक रिक्त लाइनों से मिलकर अनुक्रमों से अलग हो जाते हैं, रिक्त लाइनों के अग्रणी या अनुगामी होने से इनपुट की शुरुआत या अंत में खाली रिकॉर्ड नहीं होंगे, और <newline>हमेशा एक क्षेत्र विभाजक होगा, कोई फर्क नहीं पड़ता कि एफएस का मूल्य क्या है।

आउटपुट पैराग्राफ को अलग नहीं किया जाएगा क्योंकि आउटपुट सेपरेटर एक सिंगल न्यूलाइन रहता है। यह सुनिश्चित करने के लिए कि आउटपुट पैराग्राफ के बीच एक रिक्त रेखा है, आउटपुट रिकॉर्ड विभाजक को दो नईलाइन्स पर सेट करें:

awk -v RS='' -v ORS='\n\n' '/42B/' file

1
एक सुरुचिपूर्ण समाधान के लिए +1। हालांकि आपको फ़ाइल को पुनर्निर्देशित करने की आवश्यकता नहीं है ...
jasonwryan

उंगलियां ऑटोपायलट पर थीं।
llua

2
@ajonwryan, जब तक आपको aw ( FILENAME) के भीतर फ़ाइल नाम तक पहुँच की आवश्यकता नहीं होती है, यह पुनर्निर्देशन का उपयोग करने के लिए एक बुरा विचार नहीं है, क्योंकि फ़ाइल नाम युक्त =या शुरू होने -(या होने -) के लिए समस्याओं से बचा जाता है , लगातार त्रुटि संदेशों के लिए बनाता है, और चलने awkया प्रदर्शन से बचा जाता है अन्य पुनर्निर्देशन यदि इनपुट फ़ाइल नहीं खोली जा सकती है।
स्टीफन चेजेलस

14

यह मानते हुए कि यह संरचित है कि यह हमेशा से पहले और उसके बाद की रेखा है, आप चाहते हैं कि आप grep का उपयोग कर सकते हैं -A(बाद में) और -B(पहले) स्विच को यह बताने के लिए कि मैच से पहले 1 पंक्ति और उसके बाद 1 पंक्ति शामिल करें:

$ grep -A 1 -B 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

यदि आप खोज शब्द से पहले और बाद में समान संख्या रेखाएँ चाहते हैं, तो आप -C(संदर्भ) स्विच का उपयोग कर सकते हैं :

$ grep -C 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

यदि आप कई लाइनों से मेल खाते हुए और अधिक कड़े होना चाहते हैं, तो आप कई लाइनों के pcregrepपैटर्न का मिलान करने के लिए टूल का उपयोग कर सकते हैं :

$ pcregrep -M 'Pseudo.*\n.*42B.*\nstate.*' sample.txt
Pseudo name=Apple
Code=42B
state=fault

उपरोक्त पैटर्न निम्नानुसार मेल खाता है:

  • -M - कई लाइनें
  • 'Pseudo.*\n.*42B.*\nstate.*'- स्ट्रिंग्स के एक समूह से मेल खाता है, जहां पहली स्ट्रिंग शब्द के साथ शुरू होता है, "Pseudo"जिसके बाद किसी भी वर्ण को पंक्ति के अंत तक रखा जाता है \n, उसके बाद किसी भी वर्ण को तब तक ऊपर रखा जाता है जब तक कि स्ट्रिंग "42B"किसी भी वर्ण द्वारा पंक्ति के अंत तक ( \n), स्ट्रिंग द्वारा पीछा किया जाता है। "state"किसी भी वर्ण द्वारा पीछा किया।

5
-C(संदर्भ) एक शॉर्टकट के रूप में इस्तेमाल किया जा सकता है, अगर -Aऔर -Bसमान हैं।
डेविड बैगमैन

@DavidBaggerman - धन्यवाद। इसे उत्तर में जोड़ा गया।
स्लम

क्यों एक नीचे वोट? यह सवाल का जवाब देता है।
स्लम

4

वहाँ शायद यह जाग के साथ करने के लिए एक आसान तरीका है, लेकिन पर्ल में:

cat file | perl -ne 'BEGIN { $/="\n\n" }; print if $_ =~ /42B/;'

यह मूल रूप से फ़ाइल को रिक्त लाइनों द्वारा सीमांकित फ़ाइल में विभाजित करने के लिए कहता है, फिर केवल उन चंक्स को प्रिंट करें जो आपकी नियमित अभिव्यक्ति से मेल खाते हैं।


10
यह विकल्प और आशुलिपि का उपयोग करके सरल बनाया जा सकता है, और बेकार उपयोग कोcat खो सकता है ; perl -00 -ne 'print if /42B/' file
ट्रिपल

4

grepयूनिक्स के कुछ प्रकारों का है -p"पैरा" के लिए झंडा। मुझे पता है कि AIX करता है

grep -p 42B <myfile>

ठीक वही करेंगे जो आप वहां के लिए पूछ रहे हैं। YMMV और GNU grep में यह ध्वज नहीं है।


-P झंडा होना अद्भुत होगा। विशेष रूप से अगर -v के साथ प्रयोग किया जाता है तो आप आउटपुट से संपूर्ण पैराग्राफ को बाहर कर सकते हैं।
इलविलजा

2

अनुगामी खाली लाइन के बिना एक अन्य पर्ल समाधान:

perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo

उदाहरण

% perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
Pseudo name=Apple
Code=42B
state=fault

% cat foo
Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

1
या कम (और इस तरह अधिक पठनीय), जैसा कि ट्रिपल ने एक टिप्पणी में लिखा है perl -00 -ne 'print if /42B/' file:।
mivk
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.