जवाबों:
मान लें कि तत्व 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/ पर सभी उपलब्ध
sort set1 set2 | uniq -d
बहु-सेट के लिए काम नहीं करता है। का उपयोग करने पर विचार करें sort <(sort -u set1) <(sort -u set2) | uniq -d
।
की तरह। आपको अपने आप को छांटने से निपटने की जरूरत है, लेकिन comm
ऐसा करने के लिए इस्तेमाल किया जा सकता है, प्रत्येक पंक्ति को एक निर्धारित सदस्य के रूप में मानते हुए: अंतर के लिए -12
, अंतरंगता के -13
लिए। (और -23
आपको set2 - set1
इसके बजाय फ़्लिप किया गया अंतर देता है set1 - set2
।) यूनियन sort -u
इस सेटअप में है।
मुझे एक विशिष्ट टूल का पता नहीं है लेकिन आप ऐसा करने के लिए थोड़ी स्क्रिप्ट लिखने के लिए पायथन, और इसके सेट क्लास और ऑपरेटरों का उपयोग कर सकते हैं।
परीक्षा के लिए:
Python> s1 = set(os.listdir("/bin"))
Python> s2 = set(os.listdir("/usr/bin"))
Python> s1 & s2
set(['awk',
'basename',
'chroot', ...
Python> import os
छोटे कंसोल उपकरण "सेटॉप" अब 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
यदि आप एक फ़ाइल को लाइनों के एक सेट के रूप में देखते हैं, और फ़ाइलों को क्रमबद्ध किया गया है, तो comm
।
यदि आप लाइनों के एक (बहु) सेट के रूप में एक फाइल देखते हैं, और लाइनों को सॉर्ट नहीं किया जाता है, grep
तो अंतर और चौराहे कर सकते हैं (यह अंतर और चौराहे को प्राप्त करता है, लेकिन मल्टीसेट के लिए गिनती का सम्मान नहीं करता है)। संघ बस है cat
।
grep -xF -f small large >intersection
grep -vxF -f small large >difference
cat small large >union
मैंने ऐसा करने के लिए एक छोटा सा उपकरण लिखा है जो विभिन्न स्थानों में मेरे लिए काफी उपयोगी रहा है। UI अनपॉल है और मुझे बहुत बड़ी फ़ाइलों के लिए प्रदर्शन विशेषताओं के बारे में निश्चित नहीं है (क्योंकि यह पूरी सूची को मेमोरी में पढ़ता है) लेकिन "यह मेरे लिए काम करता है"। कार्यक्रम https://github.com/nibrahim/lines पर है । यह पायथन में है। आप इसका उपयोग करके प्राप्त कर सकते हैं pip install lines
।
यह वर्तमान में दो फाइलों के मिलन, अंतर, अंतर और सममित अंतर का समर्थन करता है। इनपुट फ़ाइल की प्रत्येक पंक्ति को एक सेट के एक तत्व के रूप में माना जाता है।
इसके दो अतिरिक्त ऑपरेशन भी हैं। एक फ़ाइल में खाली लाइनों को निचोड़ना और दूसरा (जो मेरे लिए बहुत उपयोगी है) फ़ाइल के माध्यम से देखना और इसे समान तारों के सेट में विभाजित करना है। सामान्य सूची से मेल नहीं खाने वाली सूची में फ़ाइलों को देखने के लिए मुझे इसकी आवश्यकता थी।
मैं प्रतिक्रिया का स्वागत करता हूँ।
फ़ाइलसिस्टम फ़ाइलनाम (संपूर्ण फ़ाइलनाम, पथ सहित) को अद्वितीय मानता है।
संचालन?
आप नई निर्देशिका में सेट करने के लिए खाली निर्देशिका c / / में फ़ाइलों की प्रतिलिपि a / b / कर सकते हैं।
फाइल-टेस्ट जैसे कि -e name
और लूप या मिल जाए, आप दो या अधिक निर्देशिकाओं में मौजूद फाइलों की जांच कर सकते हैं, चौराहे या अंतर को प्राप्त करने के लिए।
यहाँ सबसे अच्छा जवाब: सेटडाउन (एक समर्पित उपकरण)
मैंने सेटडाउन नामक एक कार्यक्रम लिखा जो क्ली से सेट ऑपरेशन करता है।
एक मेकफाइल में आप क्या लिखेंगे, इसकी परिभाषा लिखकर यह सेट ऑपरेशन कर सकता है:
someUnion: "file-1.txt" \/ "file-2.txt"
someIntersection: "file-1.txt" /\ "file-2.txt"
someDifference: someUnion - someIntersection
यह बहुत अच्छा है और आपको इसे देखना चाहिए। मैं व्यक्तिगत रूप से ऐसे एड-हॉक कमांड्स का उपयोग करने की सलाह नहीं देता जो सेट ऑपरेशंस को करने के लिए काम के लिए नहीं बनाए गए थे। यह तब अच्छी तरह से काम नहीं करेगा जब आपको वास्तव में कई सेट ऑपरेशन करने की आवश्यकता होती है या यदि आपके पास कोई सेट ऑपरेशन है जो एक दूसरे पर निर्भर करते हैं । इतना ही नहीं बल्कि सेटडाउन आपको सेट किए गए ऑपरेशन लिखने देता है जो अन्य सेट ऑपरेशंस पर निर्भर करता है!
किसी भी दर पर, मुझे लगता है कि यह बहुत अच्छा है और आपको इसे पूरी तरह से देखना चाहिए।
zsh
सरणियों के साथ ( zsh
सरणियों में बाइट्स का कोई भी मनमाना अनुक्रम हो सकता है, यहां तक कि 0)।
(यह भी ध्यान दें कि आप typeset -U array
इसकी गारंटी दे सकते हैं कि इसके तत्व अद्वितीय हैं)।
if ((${array[(Ie)$element]})); then
echo '$element is in $array'
fi
( I
सरणी सबस्क्रिप्ट ध्वज का उपयोग करके, सरणी में अंतिम घटना का सूचकांक प्राप्त करने के लिए $element
(या यदि नहीं मिला तो)। पैटर्न के रूप में लिए जाने के e
लिए निकालें ( e
xact के लिए $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]}