लिनक्स उपकरणों को फाइलों को सेट के रूप में मानने और उन पर सेट ऑपरेशन करने के लिए


81

क्या किसी को किसी भी लिनक्स उपकरण का पता है जो विशेष रूप से फाइलों को सेट के रूप में व्यवहार करने और उन पर सेट संचालन करने के लिए डिज़ाइन किया गया है? अंतर, चौराहा, आदि की तरह?

जवाबों:


110

मान लें कि तत्व NUL और newline के अलावा अन्य वर्णों के तार हैं (खबरदार कि फ़ाइल नाम में newline मान्य है), तो आप एक सेट को प्रति पंक्ति एक तत्व के साथ पाठ फ़ाइल के रूप में दर्शा सकते हैं और कुछ मानक यूनिक्स उपयोगिताओं का उपयोग कर सकते हैं।

सदस्यता सेट करें

$ grep -Fxc 'element' set   # outputs 1 if element is in set
                            # outputs >1 if set is a multi-set
                            # outputs 0 if element is not in set

$ grep -Fxq 'element' set   # returns 0 (true)  if element is in set
                            # returns 1 (false) if element is not in set

$ awk '$0 == "element" { s=1; exit }; END { exit !s }' set
# returns 0 if element is in set, 1 otherwise.

$ awk -v e='element' '$0 == e { s=1; exit } END { exit !s }'

अंतःकरण सेट करें

$ comm -12 <(sort set1) <(sort set2)  # outputs intersect of set1 and set2

$ grep -xF -f set1 set2

$ sort set1 set2 | uniq -d

$ join -t <(sort A) <(sort B)

$ awk '!done { a[$0]; next }; $0 in a' set1 done=1 set2

समानता सेट करें

$ cmp -s <(sort set1) <(sort set2) # returns 0 if set1 is equal to set2
                                   # returns 1 if set1 != set2

$ cmp -s <(sort -u set1) <(sort -u set2)
# collapses multi-sets into sets and does the same as previous

$ awk '{ if (!($0 in a)) c++; a[$0] }; END{ exit !(c==NR/2) }' set1 set2
# returns 0 if set1 == set2
# returns 1 if set1 != set2

$ awk '{ a[$0] }; END{ exit !(length(a)==NR/2) }' set1 set2
# same as previous, requires >= gnu awk 3.1.5

कार्डिनैलिटी सेट करें

$ wc -l < set     # outputs number of elements in set

$ awk 'END { print NR }' set

$ sed '$=' set

सबसेट टेस्ट

$ comm -23 <(sort -u subset) <(sort -u set) | grep -q '^'
# returns true iff subset is not a subset of set (has elements not in set)

$ awk '!done { a[$0]; next }; { if !($0 in a) exit 1 }' set done=1 subset
# returns 0 if subset is a subset of set
# returns 1 if subset is not a subset of set

यूनियन सेट करें

$ cat set1 set2     # outputs union of set1 and set2
                    # assumes they are disjoint

$ awk 1 set1 set2   # ditto

$ cat set1 set2 ... setn   # union over n sets

$ sort -u set1 set2  # same, but doesn't assume they are disjoint

$ sort set1 set2 | uniq

$ awk '!a[$0]++' set1 set2       # ditto without sorting

पूरक सेट करें

$ comm -23 <(sort set1) <(sort set2)
# outputs elements in set1 that are not in set2

$ grep -vxF -f set2 set1           # ditto

$ sort set2 set2 set1 | uniq -u    # ditto

$ awk '!done { a[$0]; next }; !($0 in a)' set2 done=1 set1

सममित अंतर सेट करें

$ comm -3 <(sort set1) <(sort set2) | tr -d '\t'  # assumes not tab in sets
# outputs elements that are in set1 or in set2 but not both

$ sort set1 set2 | uniq -u

$ cat <(grep -vxF -f set1 set2) <(grep -vxF -f set2 set1)

$ grep -vxF -f set1 set2; grep -vxF -f set2 set1

$ awk '!done { a[$0]; next }; $0 in a { delete a[$0]; next }; 1;
       END { for (b in a) print b }' set1 done=1 set2

सत्ता स्थापित

एक सेट प्रदर्शित अंतरिक्ष के सभी संभावित सबसेट अलग, प्रति पंक्ति एक:

$ p() { [ "$#" -eq 0 ] && echo || (shift; p "$@") |
        while read r; do printf '%s %s\n%s\n' "$1" "$r" "$r"; done; }
$ p $(cat set)

(माना जाता है कि तत्वों में SPC, TAB (डिफ़ॉल्ट मान मानकर $IFS), बैकलैश, वाइल्डकार्ड वर्ण शामिल नहीं हैं)।

कार्टेशियन उत्पाद सेट करें

$ while IFS= read -r a; do while IFS= read -r b; do echo "$a, $b"; done < set1; done < set2

$ awk '!done { a[$0]; next }; { for (i in a) print i, $0 }' set1 done=1 set2

सेट टेस्ट को खारिज करें

$ comm -12 <(sort set1) <(sort set2)  # does not output anything if disjoint

$ awk '++seen[$0] == 2 { exit 1 }' set1 set2 # returns 0 if disjoint
                                             # returns 1 if not

खाली सेट टेस्ट

$ wc -l < set            # outputs 0  if the set is empty
                         # outputs >0 if the set is not empty

$ grep -q '^' set        # returns true (0 exit status) unless set is empty

$ awk '{ exit 1 }' set   # returns true (0 exit status) if set is empty

न्यूनतम

$ sort set | head -n 1   # outputs the minimum (lexically) element in the set

$ awk 'NR == 1 { min = $0 }; $0 < min { min = $0 }; END { print min }'
# ditto, but does numeric comparison when elements are numerical

ज्यादा से ज्यादा

$ sort test | tail -n 1    # outputs the maximum element in the set

$ sort -r test | head -n 1

$ awk '$0 > max { max = $0 }; END { print max }'
# ditto, but does numeric comparison when elements are numerical

Http://www.catonmat.net/blog/set-operations-in-unix-shell-simplified/ पर सभी उपलब्ध


1
मुझे लगता है कि पायथन संस्करण बहुत सरल और अधिक सहज है। ;-)
कीथ

मुझे लगता है कि यह सबसे पूर्ण उत्तर है। दुर्भाग्य से जो चलाने के लिए या जो तर्क देता है (कॉम -12, -23, -13) प्रत्येक मामले में हमेशा "चौराहे" या "अंतर" के रूप में सहज नहीं है। शायद मैं उनके चारों ओर एक आवरण बनाऊंगा, क्योंकि मैं हमेशा इन चीजों का उपयोग कर रहा हूं।
निलटन

मैंने [पोल @ लोकलहोस्ट इंस्टा] $ grep -xc और INSTALL-BINARY 0 [पोल @ लोकलहोस्ट इंस्टैंस] $ चलाए लेकिन मुझे समझ नहीं आ रहा है कि इसका क्या मतलब है। शब्द और "फ़ाइल में कई बार होना चाहिए। मैं क्या गलत कर रहा हूं?
Vérace

1
सेट चौराहा: sort set1 set2 | uniq -dबहु-सेट के लिए काम नहीं करता है। का उपयोग करने पर विचार करें sort <(sort -u set1) <(sort -u set2) | uniq -d
नव

11

की तरह। आपको अपने आप को छांटने से निपटने की जरूरत है, लेकिन commऐसा करने के लिए इस्तेमाल किया जा सकता है, प्रत्येक पंक्ति को एक निर्धारित सदस्य के रूप में मानते हुए: अंतर के लिए -12, अंतरंगता के -13लिए। (और -23आपको set2 - set1इसके बजाय फ़्लिप किया गया अंतर देता है set1 - set2।) यूनियन sort -uइस सेटअप में है।


1
वास्तव में, कॉम ज्यादातर सामान करने के लिए लगता है। यद्यपि तर्क बहुत ही अनपेक्षित हैं। धन्यवाद!
निलटन

7

मुझे एक विशिष्ट टूल का पता नहीं है लेकिन आप ऐसा करने के लिए थोड़ी स्क्रिप्ट लिखने के लिए पायथन, और इसके सेट क्लास और ऑपरेटरों का उपयोग कर सकते हैं।

परीक्षा के लिए:

Python> s1 = set(os.listdir("/bin"))
Python> s2 = set(os.listdir("/usr/bin"))
Python> s1 & s2

set(['awk',
     'basename',
     'chroot', ...

हां, अच्छा जवाब। यदि अजगर उपलब्ध है तो awk का उपयोग क्यों करें?
गुएतली

आप भूल गए:Python> import os
जेम्स बोवेरी

7

छोटे कंसोल उपकरण "सेटॉप" अब 16.10 के बाद से डेबियन स्ट्रेच और उबंटू में उपलब्ध है। आप इसके माध्यम से प्राप्त कर सकते हैं sudo apt install setop

यहाँ कुछ उदाहरण हैं। पर सेट किए जाने वाले सेट अलग-अलग इनपुट फ़ाइलों के रूप में दिए गए हैं: setop input # is equal to "sort input --unique" setop file1 file2 --union # option --union is default and can be omitted setop file1 file2 file3 --intersection # more than two inputs are allowed setop file1 - --symmetric-difference # ndash stands for standard input setop file1 -d file2 # all elements contained in 1 but not 2

बूलियन क्वेरी केवल EXIT_SUCCESSसच के मामले में वापस आती है, और EXIT_FAILUREसाथ ही एक संदेश अन्यथा। इस तरह, सेटटॉप का उपयोग शेल में किया जा सकता है। setop inputfile --contains "value" # is element value contained in input? setop A.txt B.txt --equal C.txt # union of A and B equal to C? setop bigfile --subset smallfile # analogous --superset setop -i file1 file2 --is-empty # intersection of 1 and 2 empty (disjoint)?

मूल रूप से यह वर्णन करना भी संभव है कि इनपुट धाराओं को कैसे पार्स किया जाएगा, वास्तव में नियमित अभिव्यक्तियों द्वारा:

  • setop input.txt --input-separator "[[:space:]-]"इसका मतलब है कि व्हाट्सएप (यानी \v \t \n \r \fया स्पेस) या माइनस साइन को तत्वों के बीच विभाजक के रूप में व्याख्या की जाती है (डिफ़ॉल्ट नई लाइन है, यानी इनपुट फाइल की हर लाइन एक तत्व है)
  • setop input.txt --input-element "[A-Za-z]+" इसका मतलब है कि तत्व केवल लैटिन वर्णों से युक्त शब्द हैं, अन्य सभी वर्ण तत्वों के बीच विभाजक माने जाते हैं

इसके अलावा, आप कर सकते हैं

  • --count आउटपुट सेट के सभी तत्व,
  • --trim सभी इनपुट तत्व (यानी सभी अवांछित पूर्ववर्ती और सफल पात्रों को मिटा दें जैसे कि अंतरिक्ष, अल्पविराम आदि)।
  • रिक्त तत्वों को मान्य मानें --include-empty,
  • --ignore-case,
  • --output-separatorआउटपुट स्ट्रीम के तत्वों के बीच सेट करें (डिफ़ॉल्ट है \n),
  • और इसी तरह।

अधिक जानकारी के लिए देखें man setopया github.com/phisigma/setop


3

यदि आप एक फ़ाइल को लाइनों के एक सेट के रूप में देखते हैं, और फ़ाइलों को क्रमबद्ध किया गया है, तो comm

यदि आप लाइनों के एक (बहु) सेट के रूप में एक फाइल देखते हैं, और लाइनों को सॉर्ट नहीं किया जाता है, grepतो अंतर और चौराहे कर सकते हैं (यह अंतर और चौराहे को प्राप्त करता है, लेकिन मल्टीसेट के लिए गिनती का सम्मान नहीं करता है)। संघ बस है cat

grep -xF -f small large >intersection
grep -vxF -f small large >difference
cat small large >union

2

मैंने एक पायथन उपयोगिता बनाई है जो लाइन-वार यूनियन, चौराहे, अंतर और कई फाइलों के उत्पाद कर सकती है। इसे सेटओप कहा जाता है, आप इसे PyPI ( यहां ) पर पा सकते हैं । सिंटेक्स इस तरह दिखता है:

$ setop -i file1 file2 file3  # intersection
$ setop -d file1 file2 file3  # difference

1

मैंने ऐसा करने के लिए एक छोटा सा उपकरण लिखा है जो विभिन्न स्थानों में मेरे लिए काफी उपयोगी रहा है। UI अनपॉल है और मुझे बहुत बड़ी फ़ाइलों के लिए प्रदर्शन विशेषताओं के बारे में निश्चित नहीं है (क्योंकि यह पूरी सूची को मेमोरी में पढ़ता है) लेकिन "यह मेरे लिए काम करता है"। कार्यक्रम https://github.com/nibrahim/lines पर है । यह पायथन में है। आप इसका उपयोग करके प्राप्त कर सकते हैं pip install lines

यह वर्तमान में दो फाइलों के मिलन, अंतर, अंतर और सममित अंतर का समर्थन करता है। इनपुट फ़ाइल की प्रत्येक पंक्ति को एक सेट के एक तत्व के रूप में माना जाता है।

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

मैं प्रतिक्रिया का स्वागत करता हूँ।


0

फ़ाइलसिस्टम फ़ाइलनाम (संपूर्ण फ़ाइलनाम, पथ सहित) को अद्वितीय मानता है।

संचालन?

आप नई निर्देशिका में सेट करने के लिए खाली निर्देशिका c / / में फ़ाइलों की प्रतिलिपि a / b / कर सकते हैं।

फाइल-टेस्ट जैसे कि -e nameऔर लूप या मिल जाए, आप दो या अधिक निर्देशिकाओं में मौजूद फाइलों की जांच कर सकते हैं, चौराहे या अंतर को प्राप्त करने के लिए।


1
मेरा मतलब फाइलों की सामग्री को एक सेट के तत्वों के रूप में मानने से था (मान लें, प्रति पंक्ति एक तत्व), और फाइलें खुद को सेट के रूप में।
निलटन

0

यहाँ सबसे अच्छा जवाब: सेटडाउन (एक समर्पित उपकरण)

मैंने सेटडाउन नामक एक कार्यक्रम लिखा जो क्ली से सेट ऑपरेशन करता है।

एक मेकफाइल में आप क्या लिखेंगे, इसकी परिभाषा लिखकर यह सेट ऑपरेशन कर सकता है:

someUnion: "file-1.txt" \/ "file-2.txt"
someIntersection: "file-1.txt" /\ "file-2.txt"
someDifference: someUnion - someIntersection

यह बहुत अच्छा है और आपको इसे देखना चाहिए। मैं व्यक्तिगत रूप से ऐसे एड-हॉक कमांड्स का उपयोग करने की सलाह नहीं देता जो सेट ऑपरेशंस को करने के लिए काम के लिए नहीं बनाए गए थे। यह तब अच्छी तरह से काम नहीं करेगा जब आपको वास्तव में कई सेट ऑपरेशन करने की आवश्यकता होती है या यदि आपके पास कोई सेट ऑपरेशन है जो एक दूसरे पर निर्भर करते हैं । इतना ही नहीं बल्कि सेटडाउन आपको सेट किए गए ऑपरेशन लिखने देता है जो अन्य सेट ऑपरेशंस पर निर्भर करता है!

किसी भी दर पर, मुझे लगता है कि यह बहुत अच्छा है और आपको इसे पूरी तरह से देखना चाहिए।


0

कई फ़ाइलों के लिए नमूना पैटर्न (इस मामले में प्रतिच्छेदन):

eval `perl -le 'print "cat ",join(" | grep -xF -f- ", @ARGV)' t*`

का विस्तार:

cat t1 | grep -xF -f- t2 | grep -xF -f- t3

परीक्षण फ़ाइलें:

seq 0 20 | tee t1; seq 0 2 20 | tee t2; seq 0 3 20 | tee t3

आउटपुट:

0
6
12
18

0

zshसरणियों के साथ ( zshसरणियों में बाइट्स का कोई भी मनमाना अनुक्रम हो सकता है, यहां तक ​​कि 0)।

(यह भी ध्यान दें कि आप typeset -U arrayइसकी गारंटी दे सकते हैं कि इसके तत्व अद्वितीय हैं)।

सदस्यता निर्धारित करें

if ((${array[(Ie)$element]})); then
  echo '$element is in $array'
fi

( Iसरणी सबस्क्रिप्ट ध्वज का उपयोग करके, सरणी में अंतिम घटना का सूचकांक प्राप्त करने के लिए $element(या यदि नहीं मिला तो)। पैटर्न के रूप में लिए जाने के eलिए निकालें ( exact के लिए $element)

if ((n = ${(M)#array:#$element})); then
  echo "\$element is found $n times in \$array'
fi

${array:#pattern}ksh के पर एक परिवर्तन किया जा रहा है ${var#pattern}कि को हटा तत्वों है कि पैटर्न के रूप में सिर्फ प्रमुख बात यह है कि नमूने का मिलान को दूर करने के लिए विरोध मेल खाते हैं। (M)(के लिए मिलान किया ) अर्थ पराजयों और सभी निकाल देता है लेकिन मिलान किया तत्वों (उपयोग $~elementके लिए यह एक पैटर्न के रूप में लिया जाना चाहिए)।

चौराहा सेट करें

common=("${(@)set1:*set2}")

${set1:*set2}सरणी चौराहे करता है, लेकिन "${(@)...}"खाली तत्वों को संरक्षित करने के लिए सिंटैक्स की आवश्यकता होती है।

समानता सेट करें

[[ ${(j: :)${(q)array1}} = ${(j: :)${(q)array2}} ]]

परीक्षण कि क्या सरणियाँ समान हैं (और उसी क्रम में)। qपैरामीटर विस्तार ध्वज (जैसी चीजों के साथ समस्याओं से बचने के लिए तत्वों उद्धरण a=(1 "2 3")बनाम b=("1 2" 3)), और (j: :)एक स्ट्रिंग तुलना करने से पहले स्थान के साथ उन्हें मिलती है।

यह जांचने के लिए कि उनके पास एक ही तत्व हैं, आदेश के बावजूद, oउन्हें ऑर्डर करने के लिए ध्वज का उपयोग करें। uडुप्लिकेट को निकालने के लिए ध्वज (अद्वितीय) भी देखें ।

[[ ${(j: :)${(qo)array1}} = ${(j: :)${(qo)array2}} ]]

कार्डिनैलिटी सेट करें

n=$#array

सब्मिट टेस्ट

if ((${#array1:*array2} == ${#array2})); then
  echo '$array2 is included in $array1'
fi

संघ

union=("$array1[@]" "$array2[@]")

( डुप्लिकेट का मामला लेने के लिए typeset -Uऊपर या uपैरामीटर विस्तार ध्वज देखें )। यदि खाली स्ट्रिंग संभावित मानों में से एक नहीं है, तो आप इसे सरल बना सकते हैं:

union=($array1 $array2)

पूरक हैं

complement=("${(@)array1:|array2}")

उस के तत्वों में $array1नहीं हैं $array2

न्यूनतम / अधिकतम (शाब्दिक तुलना)

min=${${(o)array}[1]} max=${${(o)array}[-1]}

न्यूनतम / अधिकतम (दशमलव पूर्णांक तुलना)

min=${${(no)array}[1]} max=${${(no)array}[-1]}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.