कैसे पता चलेगा कि एक टेक्स्ट फाइल दूसरे का सबसेट है


12

मैं यह निर्धारित करने के लिए एक रास्ता खोजने की कोशिश कर रहा हूं कि क्या एक पाठ फ़ाइल दूसरे का सबसेट है ..

उदाहरण के लिए:

foo
bar

का सबसेट है

foo
bar
pluto

जबकि:

foo
pluto

तथा

foo
bar

एक दूसरे के उप-समूह नहीं हैं ...

क्या कमांड के साथ ऐसा करने का कोई तरीका है?

यह चेक एक क्रॉस चेक होना चाहिए, और इसे वापस करना होगा:

file1 subset of file2 :    True
file2 subset of file1 :    True
otherwise             :    False

संभावित रूप से अधिक कुशल समाधान (यदि फाइलें भी ऑर्डर की जाती हैं): github.com/barrycarter/bcapps/blob/master/…
barrycarter

जवाबों:


11

यदि उन फ़ाइल सामग्री को बुलाया जाता है file1, file2और file3पश्चाताप के क्रम में तो आप इसे निम्न-लाइनर के साथ कर सकते हैं:

 # python -c "x=open('file1').read(); y=open('file2').read(); print x in y or y in x"
 True
 # python -c "x=open('file2').read(); y=open('file1').read(); print x in y or y in x"
 True
 # python -c "x=open('file1').read(); y=open('file3').read(); print x in y or y in x"
 False

आपके उत्तर के लिए धन्यवाद .. +1 .. मुझे नहीं पता कि मेरा उत्तर स्वीकार करें क्योंकि आपका यूनिक्स-लिनक्स विशिष्ट नहीं है और मेरा उत्तर थोड़ा तेज है, जहां तक ​​मैंने इसे जांचा है .. आपको क्या लगता है?
gc5

आपका स्वागत है, अधिक यूनिक्स विशिष्ट उपकरणों के साथ निश्चित रूप से अन्य समाधान हैं। लेकिन यह पायथन के inऑपरेटर का एक अच्छा उपयोग लगता है ।
तिमो

इसमें अधिक यूनिक्स बनाने के लिए अजगर कमांड लाइन रैपर है, जैसे पाइपिंग के साथ बनाया गया है, जिसका नाम है pyp: code.google.com/p/pyp मुझे लगता है कि यह समाधान एक लाइनर टूल की तरह अधिक यूनिक्स बनाने के लिए तुच्छ है।
आईबीआर

3

के साथ perl:

if perl -0777 -e '$n = <>; $h = <>; exit(index($h,$n)<0)' needle.txt haystack.txt
then echo needle.txt is found in haystack.txt
fi

-0octalरिकॉर्ड परिसीमन को परिभाषित करता है। जब वह अष्टक संख्या 0377 (अधिकतम बाइट मान) से अधिक है, तो इसका मतलब है कि कोई सीमांकक नहीं है, यह करने के बराबर है $/ = undef। उस स्थिति में, <>किसी एकल फ़ाइल की पूर्ण सामग्री लौटाता है, वह है स्लुरप मोड

एक बार जब हमारे पास दो $hऔर $nचर में फ़ाइलों की सामग्री होती है , तो हम यह index()निर्धारित करने के लिए उपयोग कर सकते हैं कि क्या एक दूसरे में पाया जाता है।

हालांकि इसका मतलब है कि पूरी फाइलें स्मृति में संग्रहीत हैं, जिसका अर्थ है कि यह विधि बहुत बड़ी फ़ाइलों के लिए काम नहीं करेगी।

Mmappable फ़ाइलों के लिए (आमतौर पर नियमित फ़ाइलें और ब्लॉक डिवाइस की तरह अधिकांश खोज योग्य फ़ाइलें), जो mmap()फ़ाइलों पर उपयोग करके चारों ओर काम किया जा सकता है , जैसे कि Sys::Mmapपर्ल मॉड्यूल:

if 
  perl -MSys::Mmap -le '
    open N, "<", $ARGV[0] || die "$ARGV[0]: $!";
    open H, "<", $ARGV[1] || die "$ARGV[1]: $!";
    mmap($n, 0, PROT_READ, MAP_SHARED, N);
    mmap($h, 0, PROT_READ, MAP_SHARED, H);
    exit (index($h, $n) < 0)' needle.txt haystack.txt
then
  echo needle.txt is found in haystack.txt
fi

2

मुझे इस प्रश्न के लिए एक समाधान मिला

मूल रूप से मैं दो फाइलों का परीक्षण कर रहा हूं a.txtऔर b.txtइस स्क्रिप्ट के साथ:

#!/bin/bash

first_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$1" "$2" | wc -l)
second_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$2" "$1" | wc -l)

if [ "$first_cmp" -eq "0" -o "$second_cmp" -eq "0" ]
then
    echo "Subset"
    exit 0
else
    echo "Not subset"
    exit 1
fi

यदि कोई अन्य स्क्रिप्ट का सबसेट है तो अन्यथा के 0लिए वापस लौटें ।True1


% L क्या करता है? यह स्क्रिप्ट काम नहीं करती है, और मैं इसे डीबग करने की कोशिश कर रहा हूं ...
एलेक्स

मुझे वास्तव में इसका मतलब याद नहीं है %L, यह तीन साल पहले था। से man diff(वर्तमान संस्करण) का %Lअर्थ है "लाइन की सामग्री"।
जीसी ५

% L "नई" लाइन की सामग्री को प्रिंट करता है। IOW, अपरिवर्तित-लाइनों या पुरानी-पंक्तियों के लिए कुछ भी प्रिंट न करें, लेकिन नई-लाइनों के लिए लाइन की सामग्री को प्रिंट करें।
PLG

यह स्क्रिप्ट मेरे लिए काम करती है, बॉक्स से बाहर!
PLG

2

यदि f1 f2 का सबसेट है तो f1 - f2 एक खाली सेट है। उस पर निर्माण हम एक is_subset फ़ंक्शन और उससे प्राप्त फ़ंक्शन लिख सकते हैं। 2 पाठ फ़ाइलों के बीच सेट अंतर के अनुसार


Sort_files () {
  f1_sorted = "$ 1.sorted"
  f2_sorted = "$ 2.sorted"

  अगर [ ! -f $ f1_sorted]; फिर
    बिल्ली $ 1 | सॉर्ट | uniq> $ f1_sorted
  फाई

  अगर [ ! -f $ f2_sorted]; फिर
    बिल्ली $ 2 | सॉर्ट | uniq> $ f2_sorted
  फाई
}

remove_sorted_files () {
  f1_sorted = "$ 1.sorted"
  f2_sorted = "$ 2.sorted"
  rm -f $ f1_sorted
  rm -f $ f2_sorted
}

set_union () {
  Sort_files $ 1 $ 2
  बिल्ली "$ 1.sorted" "$ 2.sorted" | सॉर्ट | uniq
  remove_sorted_files $ 1 $ 2
}

set_diff () {
  Sort_files $ 1 $ 2
  बिल्ली "$ 1.sorted" "$ 2.sorted" "$ 2.sorted" | सॉर्ट | uniq -u
  remove_sorted_files $ 1 $ 2
}

rset_diff () {
  Sort_files $ 1 $ 2
  बिल्ली "$ 1.sorted" "$ 2.sorted" "$ 1.sorted" | सॉर्ट | uniq -u
  remove_sorted_files $ 1 $ 2
}

is_subset () {
  Sort_files $ 1 $ 2
  आउटपुट = $ (set_diff $ 1 $ 2)
  remove_sorted_files $ 1 $ 2

  अगर [-Z $ आउटपुट]; फिर
    वापसी ०
  अन्य
    वापसी 1
  फाई

}


क्या यह स्क्रिप्ट शुरू होनी चाहिए #!/bin/bash?
एलेक्स

2

से http://www.catonmat.net/blog/set-operations-in-unix-shell/ :

कॉम दो क्रमबद्ध फ़ाइलों की तुलना लाइन द्वारा करता है। इसे इस तरह से चलाया जा सकता है कि यह उन लाइनों को आउटपुट करता है जो केवल पहली निर्दिष्ट फ़ाइल में दिखाई देती हैं। यदि पहली फ़ाइल दूसरे का सबसेट है, तो पहली फ़ाइल की सभी पंक्तियाँ भी 2 में दिखाई देती हैं, इसलिए कोई आउटपुट उत्पन्न नहीं होता है:

$ comm -23 <(sort subset | uniq) <(sort set | uniq) | head -1
# comm returns no output if subset ⊆ set
# comm outputs something if subset ⊊ set
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.