फ़ाइल के अंत तक मैच के बाद सभी लाइनों को कैसे प्रिंट करें?


48

इनपुट फ़ाइल 1 है:

dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

मैं other file( dog 123 4335फाइल 2 से) की तरह मैच को पैटर्न देता हूं ।

मैं लाइन के पैटर्न से मेल खाता हूं dog 123 4335और मैच लाइन के बिना सभी लाइनों को प्रिंट करने के बाद मेरा आउटपुट है:

cat 13123 23424
deer 2131 213132
bear 2313 21313

यदि केवल लाइन के पते के बिना उपयोग केवल पैटर्न का उपयोग करते हैं, उदाहरण के 1s लिए लाइनों से कैसे मेल और प्रिंट करें?


क्या अन्य फ़ाइल में प्रति पंक्ति या खोज करने के लिए केवल एक ही पैटर्न हो सकता है, और जो भी खोज की गई फ़ाइल में सबसे पहले मिल जाए, उसे खोजना शुरू कर दें?
सिरो सेंटिल्ली 新疆 i iro i 事件 ''

जवाबों:


27

यह मानते हुए कि आप अपने पैटर्न के साथ जीएनयू के साथ पूरी लाइन का मिलान करना चाहते हैं sed, यह काम करता है:

sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile

मानक समकक्ष:

sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile

निम्नलिखित इनपुट के साथ ( infile):

cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

आउटपुट है:

cat 13123 23424 
deer 2131 213132
bear 2313 21313

स्पष्टीकरण:

  • /^dog 123 4335$/ वांछित पैटर्न के लिए खोज करता है।
  • :a; n; p; ba;एक लूप है जो इनपुट से एक नई लाइन प्राप्त करता है ( n), इसे प्रिंट करता है ( p), और शाखाओं को वापस लेबल करता है a :a; ...; ba;

अपडेट करें

यहाँ एक उत्तर है जो आपकी आवश्यकताओं के करीब आता है, यानी फ़ाइल 2 में पैटर्न, फ़ाइल 1 से पकड़ना:

tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1

एम्बेडेड grep और कट फ़ाइल 2 से एक पैटर्न वाली पहली पंक्ति को ढूंढते हैं, यह लाइन नंबर प्लस एक पूंछ पर पारित की जाती है, प्लस एक पैटर्न के साथ लाइन को छोड़ना है।

यदि आप पहले मैच के बजाय पिछले मैच से शुरुआत करना चाहते हैं तो यह होगा:

tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1

ध्यान दें कि पूंछ के सभी संस्करण प्लस-नोटेशन का समर्थन नहीं करते हैं।


यह sed में n और p कमांड का पहला उदाहरण है जो मैंने देखा है कि ऐसा नहीं लगता है कि sed बहुत दूर तक ले जा रहा है। ऐसा लगता है (मेरे संक्षिप्त परीक्षणों से) sed -n '/^dog 123 4335$/ { :a; p; n; ba; }' infile(पी और एन स्विच के साथ) सफलतापूर्वक उस रेखा को भी शामिल करता है जो मेल खाती है।
जोशियाह योडर

26

यदि आपके पास एक बहुत छोटी फ़ाइल है तो grepअकेले काम कर सकता है:

grep -A5000 -m1 -e 'dog 123 4335' animals.txt

5000 "उचित रूप से कम" पर मेरा अनुमान है, जैसा grepकि पहला मैच पाता है और इसे अगली 5000 लाइनों के साथ एक साथ आउटपुट करता है (फ़ाइल को कई होने की आवश्यकता नहीं है)। यदि आप मैच नहीं चाहते हैं तो आपको इसे काटने की आवश्यकता होगी, जैसे

grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2


यदि आप पहला नहीं चाहते हैं, लेकिन अंतिम मैच परिसीमाक के रूप में आप इसका उपयोग कर सकते हैं:

tac animals.txt | sed -e '/dog 123 4335/q' | tac

यह लाइन animals.txtलाइनों के रिवर्स ऑर्डर में पढ़ती है और लाइन के साथ आउटपुट को शामिल और शामिल करती है dog 123 4335और फिर उचित ऑर्डर को पुनर्स्थापित करने के लिए फिर से पलट देती है।

फिर, यदि आपको परिणाम में मैच की आवश्यकता नहीं है, तो पूंछ जोड़ें। (आप छोड़ने से पहले इसके बफर को छोड़ने के लिए sed अभिव्यक्ति को भी जटिल कर सकते हैं।)


मेरे परीक्षण से, GNU grep 3.0 आफ्टर-रेफरेंस (निर्दिष्ट मूल्य की परवाह किए बिना) में 132 लाइनों से अधिक आउटपुट नहीं करता है।
रुविम

22

व्यवहार में मैं शायद का उपयोग करेंगे Aet3miirah का जवाब समय और के सबसे एलेक्सी का जवाब जब पंक्तियां (, यह भी साथ काम करता है के माध्यम से नेविगेट के लिए इच्छुक अद्भुत है less)। OTOH, मैं वास्तव में एक और दृष्टिकोण पसंद करता हूं (जो उलटा गाइल्स के उत्तर की तरह है :

sed -n '/dog 123 4335/,$p'

जब -nध्वज के साथ कहा जाता है , sedतो डिफ़ॉल्ट रूप से उन लाइनों को प्रिंट नहीं करता है जो इसे और अधिक संसाधित करता है। फिर हम एक 2-एड्रेस फॉर्म का उपयोग /dog 123 4335/करते हैं जो फ़ाइल के अंत तक लाइन से एक कमांड लागू करने के लिए कहता है (द्वारा प्रतिनिधित्व किया गया $)। विचाराधीन कमांड है p, जो वर्तमान लाइन को प्रिंट करता है। तो, इसका मतलब है "एक मिलान से सभी पंक्तियों /dog 123 4335/को अंत तक प्रिंट करें ।"


3
यह उस dogरेखा को प्रिंट करता है, जो यहाँ नहीं है।
स्टीफन चेजालस

1
यह सबसे अच्छा उत्तर (और मेरे स्वयं के मामले के लिए काम करता है) जैसा दिखता है, लेकिन मिलान की हुई रेखा को भी छोड़ने के लिए अनुकूलित करने की आवश्यकता होगी।
पावेल Paमरदा

1
sed -n '/ dog 123 4335 /, $ p' | sed '1d' कुत्ते की लाइन को हटा देगा
केमिन झोउ

1
sed -n '/dog 123 4335/,$p' | tail -n +2के रूप में अच्छी तरह से मैच निकाल देंगे
gilad mayani

15
sed -e '1,/dog 123 4335/d' file1

यदि आपको किसी फ़ाइल से पैटर्न को पढ़ने की आवश्यकता है, तो इसे sed कमांड में स्थान दें। यदि फ़ाइल में एक sed प्रतिमान है:

sed -e "1,/$(cat file2)/d" file1

यदि फ़ाइल में देखने के लिए शाब्दिक स्ट्रिंग है, तो सभी विशेष वर्णों को उद्धृत करें। मुझे लगता है कि फाइल में एक ही लाइन है।

sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1

यदि आप चाहते हैं कि मैच पूरी लाइन हो, न कि केवल एक विकल्प के रूप में, पैटर्न को लपेटें ^…$

sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1

6
अगर पैटर्न पहली पंक्ति में है तो यह काम नहीं करेगा। GNU sedके 0,/dog.../dलिए है।
स्टीफन चेज़लस

14

$ more +/"dog 123 4335" file1


4
यह भी साथ काम करता है less
ब्रांडीजी

3
टर्मिनल पर चालाक, लेकिन यह वास्तव में काम नहीं करता है अगर आप इसे किसी और चीज़ में पाइप करते हैं tac
jcomeau_ictx

मैं इसे इस तरह से उपयोग कर रहा हूं, $ अधिक + / "मेरे शब्दों से मेल खाएं" file1 >> file2
AMB

1
शायद POSIX 7 +द्वारा प्रतिस्थापित किया गया था -p: pubs.opengroup.org/onlinepubs/9699919799/utilities/more.html लेकिन अभी तक उपयोग-लिनेक्स 2.20.1 में लागू नहीं किया गया है। और यह भी प्रिंट करता है skipping..और कुछ अतिरिक्त न्यूलाइन्स (मुझे उम्मीद है कि ऐसा करने के लिए, यह ठीक हो सकता है)।
सिरो सेंटिल्ली 新疆 i i i 事件 '14

शायद तब से चीजें बदल गई हैं? मेरी टिप्पणी को 3 अपवोट्स मिले, इसलिए यह उस समय प्रासंगिक हो सकता है ...
jcomeau_ictx


5

Awk का उपयोग करने का एक तरीका:

awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}'  file2 file1

जहाँ file2 में आपके खोज पैटर्न होते हैं। सबसे पहले, फ़ाइल 2 की सभी सामग्री सरणी "ए" में संग्रहीत की जाती है। जब फ़ाइल 1 को संसाधित किया जाता है, तो हर पंक्ति को सरणी के खिलाफ जांचा जाता है, और केवल मौजूद नहीं होने पर मुद्रित किया जाता है।


मुझे लगता है कि ओपी पैटर्न का पालन करते हुए हर लाइन का उत्पादन करना चाहता है।
Thor

@ थोर: इसे इंगित करने के लिए धन्यवाद, अब इसे अपडेट किया गया ...
गुरु

अच्छी तरह से किया :)।
थोर

5

इनपुट एक है lseekable नियमित रूप से फ़ाइल:

GNU के साथ grep:

{ grep  -xFm1 'dog 123 4335' >&2
  cat; } <infile 2>/dev/null >outfile

के साथ sed:

{ sed -n '/^dog 123 4335$/q'
  cat; } <infile >outfile

एक GNU grepजिसे w / -mविकल्प कहा जाता है , मैच में इनपुट छोड़ देगा - और यह अपना अंतिम मैच मिलने के तुरंत बाद अपने (lseekable) इनपुट fd को छोड़ देगा । इसलिए कॉलिंग grepw / -m1एक फाइल में एक पैटर्न की पहली घटना का पता लगाता है, और इनपुट को ऑफसेट catकरने के लिए फ़ाइल में पैटर्न के पहले मैच के बाद सब कुछ लिखने के लिए सही जगह पर इनपुट ऑफसेट छोड़ देता है ।

GNU के बिना भी grepआप ठीक वही काम कर सकते हैं w / एक POSIX संगत sed- जब sed quits यह अपने इनपुट ऑफसेट को सही करने के लिए निर्दिष्ट किया जाता है जहां यह होता है। जीएनयू sedइस तरह से मानकों के अनुरूप नहीं है, हालांकि, और इसलिए ऊपर संभवतः w / GNU काम नहीं करेगा sedजब तक कि आप इसे इसके -uस्विच के साथ नहीं बुलाते ।


ध्यान दें, sedयहां प्रदर्शित स्ट्रीम साझाकरण विशेष रूप से (हालांकि, हाँ, मानक संदर्भित विशेष sedरूप से उपयोगिता के रूप में उदाहरण के रूप में सक्षम नहीं है) मुक्त रूप और सशर्त रूप से सहकारी कार्यप्रवाह दिखाया गया है। विशेष रूप से, सभी मानक उपयोगिताओं का मतलब है और इस प्रकार निर्दिष्ट करना और इनपुट स्ट्रीम के कर्सर पदों को साझा करना है, अगले पाठक को किसी भी प्रसंस्करण को विफल किए बिना। grep -qयह करना चाहिए; grepजैसे ही इनपुट में कोई भी मिलान पाया जाता है, चुपचाप वापस आ जाना चाहिए, और किसी भी शेष इनपुट को मानक रूप से, डिफ़ॉल्ट रूप से उपभोग नहीं किया जाना चाहिए।
mikeserv

4

एक दूसरी फ़ाइल में पैटर्न संग्रहीत किए बिना, विषय में प्रश्न के लिए मेरा उत्तर। यहाँ मेरी परीक्षण फ़ाइल है:

$ cat animals.txt 
cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

GNU sed:

 $ sed '0,/^dog 123 4335$/d' animals.txt 
 cat 13123 23424 
 deer 2131 213132
 bear 2313 21313

पर्ल:

$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

एक फ़ाइल में पैटर्न के साथ पर्ल संस्करण:

$ cat pattern.txt 
dog 123 4335
$ perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

2

Wth ed:

ed -s file1 <<< '/dog 123 4335/+1,$p'

यह pयहां एक स्ट्रिंग में एड करने के लिए एक रिंट कमांड भेजता है ; प्रिंट कमांड एक के बाद एक सीमा तक सीमित है ( +1) dog 123 4335फ़ाइल के अंत तक मैच ( $)।


1

यदि आपके पास एक अस्थायी फ़ाइल बनाने का मन नहीं है, और csplitउपलब्ध है, तो यह काम करती है:

sh -c 'csplit -sf"$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2

नोट file1इनपुट फ़ाइल है और file2पैटर्न फ़ाइल है (जैसा कि प्रश्न में कहा गया है)।

उपरोक्त आदेश का लंबा रूप है:

sh -c 'csplit --quiet --prefix="$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2

अर्थात,

csplit --quiet --prefix="file1_" "file1" "%^$(cat "file2")%+1" && cat "file1_00"

csplitprefixऊपर ध्वज के बिना फ़ाइल बनाएगा xx00(उपसर्ग xx, और प्रत्यय होने के नाते 00)। इसके ऊपर के झंडे के साथ यह फाइल बनाता है file1_00quietध्वज के बिना , यह आउटपुट फ़ाइल आकार (परिणामस्वरूप फ़ाइल का आकार) प्रिंट करता है।


0

चूंकि awk स्पष्ट रूप से अस्वीकृत नहीं है, इसलिए यहां 'कैट' मानने की मेरी पेशकश मैच है।

awk '$0 ~ /cat/ { vart = NR }{ arr[NR]=$0 } END { for (i = vart; i<=NR ; i++) print arr[i]  }' animals.txt

0

फ़ाइल के अंत तक मैच के बाद सभी लाइनों को कैसे प्रिंट करें?

एक अन्य तरीका यह डाल करने के लिए "कैसे (सहित) मैच तक 1 एक से सभी लाइनों को हटाने के लिए", और यह हो सकता है sedके रूप में -written:

sed -e '1,/MATCH PATTERN/d'

1
एकमात्र समस्या यह है कि जब पैटर्न पहली पंक्ति पर है ...
don_crissti


मुझे लगता है कि हमें निर्णय लेने के लिए यहां एक समिति की आवश्यकता है।
poige

1
@ छोटा: नाह, आप एक ही जवाब कम व्यापक रूप से प्रदान करते हैं
थोर

@don_crissti, sed -e '0,/MATCH PATTERN/d'तब के बारे में क्या ?
वेलकन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.