답변:
요소가 NUL 및 개행 문자 이외의 문자 스트링이라고 가정하면 (개행은 파일 이름에서 유효 함) 행당 하나의 요소가있는 텍스트 파일로 세트 를 표시하고 일부 표준 Unix 유틸리티를 사용할 수 있습니다.
$ 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
.
특정 도구를 모르지만 Python과 해당 클래스 및 연산자를 사용하여 작은 스크립트를 작성하여 사용할 수 있습니다.
예를 들어 :
Python> s1 = set(os.listdir("/bin"))
Python> s2 = set(os.listdir("/usr/bin"))
Python> s1 & s2
set(['awk',
'basename',
'chroot', ...
Python> import os
작은 콘솔 툴“setop”은 이제 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
는 true 인 경우 에만 반환 되고 EXIT_FAILURE
그렇지 않으면 메시지가 반환됩니다. 이런 식으로 setop을 쉘에서 사용할 수 있습니다.
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 자세한 내용은.
나는 여러 곳에서 나에게 매우 유용한이 작업을 수행하는 작은 도구를 작성했습니다. UI가 연마되지 않았으며 매우 큰 파일의 성능 특성이 확실하지 않습니다 (전체 목록을 메모리로 읽어들이므로). 프로그램은 https://github.com/nibrahim/lines에 있습니다. 파이썬으로되어 있습니다. 를 사용하여 얻을 수 있습니다 pip install lines
.
현재 두 파일의 합집합, 교집합, 차이 및 대칭 차이를 지원합니다. 입력 파일의 각 행은 세트의 요소로 취급됩니다.
또한 두 가지 추가 작업이 있습니다. 파일에서 빈 줄을 짜내고 두 번째는 (나에게 매우 유용했습니다) 파일을 살펴보고 유사한 문자열 세트로 나누는 것입니다. 일반적인 패턴과 일치하지 않는 목록에서 파일을 찾으려면 이것이 필요했습니다.
의견을 환영합니다.
가장 좋은 답변은 : Setdown (전용 도구)
cli에서 Set 작업을 수행하는 setdown이라는 프로그램을 작성했습니다.
Makefile에 작성하는 것과 유사한 정의를 작성하여 세트 조작을 수행 할 수 있습니다.
someUnion: "file-1.txt" \/ "file-2.txt"
someIntersection: "file-1.txt" /\ "file-2.txt"
someDifference: someUnion - someIntersection
꽤 시원하고 확인해야합니다. 개인적으로 작업을 위해 설정되지 않은 임시 명령을 사용하여 집합 작업을 수행하지 않는 것이 좋습니다. 실제로 많은 집합 작업을 수행해야하거나 서로 의존하는 집합 작업이있는 경우 제대로 작동하지 않습니다. . 뿐만 아니라 setdown을 사용하면 다른 set 연산에 의존하는 set 연산을 작성할 수 있습니다!
어쨌든, 나는 그것이 매우 시원하다고 생각하며 완전히 확인해야합니다.
로 zsh
배열 ( zsh
배열 바이트의 임의의 시퀀스도 포함 할 수있는 0).
(또한 typeset -U array
요소가 고유하다는 것을 보장하기 위해 할 수 있음에 유의하십시오 ).
if ((${array[(Ie)$element]})); then
echo '$element is in $array'
fi
( I
배열 첨자 플래그를 사용하여 배열에서 마지막으로 발생하는 색인을 가져 $element
옵니다 (또는 찾을 수없는 경우 0). 패턴으로 사용하기 e
위해 제거 ( e
xact의 경우 $element
)
if ((n = ${(M)#array:#$element})); then
echo "\$element is found $n times in \$array'
fi
${array:#pattern}
패턴과 일치하는 선행 부분을 제거하는 대신 패턴과 일치하는 요소 ${var#pattern}
를 제거 하는 ksh의 변형 입니다. (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]}