फ़ाइल 2 से लाइनों (फ़ाइल 1 की सामग्री) का सटीक ब्लॉक grep


9

मेरे पास दो फाइलें हैं, file1और file2

का नमूना सामग्री file1है:

A B
C D
E F
G H

और की सामग्री इस प्रकार file2है:

A B
few other lines
E F
few more other lines
A B
C D
E F
G H
few more other lines
G H

इसलिए मैं केवल file1सामग्री के पूरे ब्लॉक को खोजना चाहता हूं file2। इसका मतलब है कि आउटपुट में केवल ये लाइनें होनी चाहिए:

A B
C D
E F
G H

कृपया ध्यान दें कि: - केवल वही लाइनें जो एक साथ आ रही हैं, आउटपुट का हिस्सा होना चाहिए।


मुझे आपका सवाल नहीं आता। यदि आप केवल file1और कुछ नहीं की सटीक सामग्री प्रिंट करना चाहते हैं , तो बस उपयोग करें cat file1
वाइल्डकार्ड

@Wildcard वह देखना चाहता है कि क्या file2 में file1 जैसी ही सामग्री है। इसके बारे में इस तरह से सोचें जैसे कि किसी पुस्तक में एक विशिष्ट अध्याय की तलाश है
सर्जियो कोलोडियाज़नी

मैं इसे फिर से खोलने के लिए मतदान कर रहा हूं क्योंकि "सेट सदस्य" कई लाइनों से बने होते हैं (मैं पहली बार में हाजिर नहीं था), जो प्रस्तावित डुप्लिकेट प्रश्न के स्वीकृत उत्तर द्वारा नियंत्रित एकल लाइनों की तुलना में थोड़ा अधिक जटिल है।
Kusalananda

1
यह सेट के बारे में नहीं है। यदि आप इसे डुप्लिकेट के रूप में चिह्नित करना चाहते हैं, तो कम से कम मल्टी-लाइन regexps के बारे में एक और प्रश्न ढूंढें।
माइकल व्हील्स

जवाबों:


11

grepजब यह मल्टीलाइन पैटर्न की बात आती है, तो यह बहुत ही बेवकूफी है, लेकिन \nपैटर्न और टेक्स्ट दोनों के न्यूलाइन अक्षरों का अनुवाद करने \0से पहले एनयूएल के पात्रों में खोज की जाती है ताकि वे इसे ठीक कर सकें। \0वापस आउटपुट में अनुवाद \nकरना स्पष्ट रूप से आवश्यक है।

यहां आपकी आज्ञा है, यह मानते हुए कि file1आपके द्वारा खोजा जाने वाला पैटर्न है file2:

grep -aof <(tr '\n' '\0' < file1) <(tr '\n' '\0' < file2) | tr '\0' '\n'

आपकी दी गई फ़ाइलों के लिए उदाहरण आउटपुट:

A B
C D
E F
G H

स्पष्टीकरण:

  • <(tr '\n' '\0' < file1)एक FIFO / नामित पाइप / अस्थायी फ़ाइल-जैसी ऑब्जेक्ट बनाता है जो बराबर होता है file1, लेकिन NUL वर्णों में अनुवादित सभी नईलाइन वर्णों के साथ।
  • <(tr '\n' '\0' < file2)वही करता है, लेकिन के लिए file2
  • grep -f PATTERN_FILE INPUT_FILEसे पैटर्न के लिए खोज करता PATTERN_FILEहै INPUT_FILE
  • बाइनरी फ़ाइलों पर मिलान सक्षम करने का -aध्वज grep। इसकी आवश्यकता है क्योंकि अन्यथा यह उन फ़ाइलों को छोड़ देगा जिनमें गैर-मुद्रण योग्य वर्ण होते हैं जैसे \0
  • इसे बनाने का -oझंडा grepकेवल मिलान अनुक्रम को प्रिंट करता है, न कि पूरी लाइन जहां यह पाया गया है।
  • | tr '\0' '\n' सभी NUL वर्णों को कमांड के आउटपुट से बाईं ओर वापस newline वर्णों में अनुवाद करता है।


3

बस शुद्ध बैश में मनोरंजन के लिए

mapfile -t <file1
while read line ; do
    [ "$line" = "${MAPFILE[i++]}" ] || { ["$line" = "$MAPFILE" ] && i=1 || i=0; }
    [ $i -eq ${#MAPFILE[*]} ] && { printf "%s\n" "${MAPFILE[@]}"; i=0; }
done <file2

3

यहाँ एक थोड़ा और अधिक सुरुचिपूर्ण है grep+ perl:

$ grep -Pzo "$(perl -pe 's/\n/\\n/g' file1.txt )"  file2.txt                    
A B
C D
E F
G H

हालांकि, एक बड़ा कैच है। यदि कोई अनुगामी न्यूलाइन है file1, तो पैटर्न दूसरे शब्दों में सही नहीं होगा A B\nC D\nE F\nG H\n\n:।

(पर्ल पार्ट प्रदान करने के लिए विशेष धन्यवाद @terdon)

जैसा कि उल्लेख किया गया है, perl -0pe 's/\n(\n+$)?/\\n/g' दूसरे perlआदेश के स्थान पर उपयोग कर सकते हैं ताकि ट्रेसिंग न्यूलाइन से बचा जा सकेfile1.txt


1
यदि कोई अनुगामी न्यूलाइन है और वह नहीं है जिसे ओपी ढूंढना चाहता है perl -0pe 's/\n(\n+$)?/\\n/g'। बिना regex modificator अतिरिक्त है। -0g
कोस्टा

1

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

import sys
find = open(sys.argv[1]).read()
hay = open(sys.argv[2]).read()
print("The text occurs", hay.count(find), "times")

आप file1जितनी बार मैच करते हैं, उतनी बार प्रिंट करना चाहते हैं ? अंतिम पंक्ति को इसके साथ बदलें:

print(find * hay.count(find))

यदि आप वास्तव में चाहते हैं, तो आप सब कुछ एक कमांडलाइन कॉल या उपनाम में पैक कर सकते हैं:

python -c 'import sys; print("The text occurs", open(sys.argv[2]).read().count(open(sys.argv[1]).read()), "times")' file1 file2

1
grep -lir 'A B \n D C \n whatever' ./folder_to_search

परिणाम सटीक पाठ मिलान वाली सभी फाइलें होंगी


0

यहां अजगर का उपयोग करने का एक और तरीका है ( python3 3.5.2बिना किसी शिकायत के साथ परीक्षण किया गया pylint3 1.5.6):

""" Locate entire file contents contiguous in other file """

import sys
import re
from mmap import mmap, PROT_READ

def memmap(name):
    """ Return memoryview of readonly mmap """
    with open(name, 'rb') as file:
        return memoryview(mmap(file.fileno(), 0, access=PROT_READ))

def finder(needle, haystack):
    """ Return iterator """
    return re.compile(re.escape(needle)).finditer(haystack)

print(tuple(finder(*(memmap(name) for name in sys.argv[1:3]))))

के माध्यम से कमांड लाइन तर्कों की हैंडलिंग सामान्य रूप से sys.argvसरल है। आप finderजिन दो memoryviewवस्तुओं को पास करते हैं, उन पर इसे पास करने के अलावा, कई अन्य चीजें भी कर सकते हैं tuple। इसके SRE_Matchद्वारा लौटाए गए प्रत्येक आइटम में पुनरावृत्ति करने वाले द्वारा finderकई प्रकार की विधियाँ होती हैं, जिनमें से एक नमूने को printआउटपुट में संक्षेपित किया जाता है ( spanउदाहरण के लिए, प्रत्येक मैच की बाइट रेंज बताता है)।

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