मैं लगातार दो लाइनों की सामग्री के आधार पर एक निर्देशिका कैसे प्राप्त कर सकता हूं?


11

मैं उन पंक्तियों के लिए एक निर्देशिका कैसे प्राप्त कर सकता हूं जिनमें "फू" शामिल हैं, लेकिन केवल तब मिलते हैं जब अगली पंक्ति में "बार" भी होता है?


समस्या अब मूल से बिल्कुल अलग है: / शायद पुराने संस्करणों को वापस करने के लिए बेहतर है और एक और पोस्ट को पोस्ट करें? इसके अलावा मेरे लिए नया प्रश्न स्पष्ट नहीं है।
गाइल्स क्वेनोट

@sputnick - ऐसा कैसे? जब मैंने पहली बार प्रश्न पोस्ट किया था तब मैंने एक निर्देशिका निर्दिष्ट की थी; मैंने केवल इसे बोल्ड किया क्योंकि लोग ध्यान नहीं दे रहे थे।
नाथन लॉन्ग

कोई बात नहीं, मैं काम करूंगा, मैं अपने POST को तदनुसार संपादित करूंगा।
गिलेस कोटेनोट

जवाबों:


7

@ warl0ck ने मुझे सही दिशा में जाने का इशारा किया pcregrep, लेकिन मैंने कहा "में" है, "नहीं" है, और मैंने एक निर्देशिका के बारे में पूछा, न कि एक फाइल के बारे में।

यह मेरे लिए काम करने लगता है।

pcregrep -rMi 'Foo(.*)\n(.*)Bar' .

6

ग्रीप स्वयं इसका समर्थन नहीं करता है, इसके बजाय pcregrep का उपयोग करें:

Foo
Bar
Foo
abc

pcregrep -M "Foo\nBar" file

समझे:

Foo
Bar

3
ओपी ने ऐसा नहीं कहा Fooऔर Barइसमें पूरी लाइन शामिल होगी।
tojrobinson

6

एक sedस्क्रिप्ट के साथ :

#!/bin/sed -nf

/^Foo/{
    h         # put the matching line in the hold buffer
    n         # going to nextline
    /^Bar/{   # matching pattern in newline
        H     # add the line to the hold buffer
        x     # return the entire paragraph into the pattern space
        p     # print the pattern space
        q     # quit the script now
    }
}

इसके प्रयेाग के लिए :

chmod +x script.sed
printf '%s\n' * | ./script.sed

printfयहाँ एक लाइन प्रत्येक पर मौजूदा निर्देशिका में सभी फ़ाइलों को प्रदर्शित करते हैं, और यह करने के लिए पारित sed

नोट : यह वर्णानुक्रम द्वारा क्रमबद्ध किया गया है।

अधिक उपयोगी pattern spaceऔर hold space यहाँ के infos ।

grymoire.com में shellप्रोग्रामिंग के बारे में बहुत अच्छी चीजें हैं ।


क्या h, n, H, x, p, qमतलब है? बहुत ही रोचक।
यमनकेओ

मेरी टिप्पणियों को देखें। अधिक infos on pattern space& hold space: grymoire.com/Unix/Sed.html#uh-56 या फ्रेंच में commentcamarche.net/faq/9536-sed-introduction-a-sed-part-i
गाइल्स क्वेना

POST ने एक निर्देशिका पर काम करने के लिए अनुकूलित किया
गिलेस क्वेनोट

4

grepकेवल का उपयोग करके , आप निम्नलिखित पाइप का निर्माण कर सकते हैं:

grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'

पहले grepउन सभी लाइनों को प्राप्त Fooकरेंगे जिनमें मैच के बाद की रेखा शामिल है। फिर हमें वे लाइनें मिलती हैं जिनमें Barमैच से पहले की रेखा भी होती है , और अंत में इस आउटपुट से रेखाओं को निकालते हैं जो इसमें होते हैं Foo

EDIT: जैसा कि मैनटवर्क ने बताया है, कुछ समस्याग्रस्त मामले हैं जो देखने योग्य हैं। हालांकि एक दिलचस्प चुनौती है, grep'लाइन ओरिएंटेड फंक्शनलिटी' की वजह से , इसके साथ कोई भी समाधान 'हैक' होने की संभावना है और आप शायद किसी ऐसी चीज़ का उपयोग करने से बेहतर हैं, pcregrepजो हाथ में काम करने के लिए अधिक अनुकूल है।


अच्छा लगा। मैंने हालांकि एक निर्देशिका के बारे में पूछा; यह काम करने लगता है:find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
नाथन लॉन्ग

यह भी एक ही लाइन पर दोनों "फू" और "बार" के साथ घटनाओं की सूची होगी।
मैनटवर्क

@manatwork: वे पंक्तियाँ जिनमें "फू" और "बार" शामिल हैं, "पंक्तियाँ जिनमें 'फू' शामिल हैं" जो कि पूछी गई थीं।
tojrobinson

1
@tojrobinson, "के बारे में क्या" लेकिन केवल मैच मिलते हैं जब अगली पंक्ति में "बार" भाग शामिल होता है? pastebin.com/Yj8aeCEA
मैनटवर्क

3

जबकि मैं नाथन के समाधान का उपयोग करना पसंद करता हूँ pcregrep, यहाँ केवल grep का उपयोग करके समाधान है

grep -o -z -P  'Foo(.*)\n(.*)Bar' file

विकल्प स्पष्टीकरण:

  • -oकेवल मिलान किए गए भाग को प्रिंट करें। आवश्यक शामिल किए जाने के बाद से -zपूरी फाइल का प्रिंटआउट लिया जाएगा (जब तक कि कहीं एक \ 0 नहीं है)
  • -z इनपुट को लाइनों के एक सेट के रूप में मानें, प्रत्येक को एक शून्य बाइट (ASCII NUL वर्ण) द्वारा एक नई रेखा के बजाय समाप्त किया जाता है।
  • -P पर्ल रेगेक्स सिंटैक्स

संपादित करें: यह संस्करण संपूर्ण मिलान वाली रेखाओं को प्रिंट करता है

    grep -o -P -z  '(.*)Foo(.*)\n(.*)Bar(.*)' file

1
कूल क्या चाल -z। पूरी अभिव्यक्ति से पहले और बाद में कुछ "(। *)" यह पूरे मिलान लाइनों का उत्पादन करेगा। अब "फू" से पहले और "बार" के बाद सबस्ट्रिंग प्रदर्शित नहीं होते हैं।
मैनावर्क

1

Awk के साथ:

awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
     /foo/ {prev=$0; next}
     {prev=""}' file1...

(awk limitation के बारे में सामान्य टिप्पणी: सावधान रहें कि यदि कुछ फ़ाइल नामों में "=" अक्षर हो सकते हैं, तो आपको जागने के ./filenameबजाय उन्हें पास करना होगा filename)

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