파일을 세트로 취급하고 세트 작업을 수행하는 Linux 도구


81

누구나 파일을 세트로 취급하고 세트 작업을 수행하도록 특별히 설계된 Linux 도구를 알고 있습니까? 차이, 교차로 등?

답변:


110

요소가 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/ 에서 모두 이용 가능


1
파이썬 버전이 훨씬 간단하고 직관적이라고 생각합니다. ;-)
Keith

이것이 가장 완전한 대답이라고 생각합니다. 불행히도 어떤 명령을 실행하거나 각 인수에서 어떤 인수 (comm -12, -23, -13)가 항상 "교차"또는 "차이"라고 직관적 인 것은 아닙니다. 나는 항상 이것들을 사용하고 있기 때문에 어쩌면 그들 주위에 래퍼를 만들 것입니다.
nilton

[pol @ localhost inst] $ grep -xc 및 INSTALL-BINARY 0 [pol @ localhost inst] $를 실행했지만 그 의미를 이해하지 못합니다. 단어 "and"는 파일에서 여러 번 나타납니다. 내가 무엇을 잘못하고 있지?
Vérace

1
교차 설정 : sort set1 set2 | uniq -d다중 세트에는 작동하지 않습니다. 사용을 고려하십시오 sort <(sort -u set1) <(sort -u set2) | uniq -d.
neo

11

일종의. 당신은 스스로 정렬을 처리해야하지만 comm, 각 라인을 세트 멤버로 취급 -12하여 교차를 -13위해, 차이 를 위해 그렇게 할 수 있습니다 . (그리고 대신에 -23차이점을 뒤집습니다 .) Union 이이 설정에 있습니다.set2 - set1set1 - set2sort -u


1
실제로, 통신은 대부분의 작업을 수행하는 것 같습니다. 논쟁은 매우 직관적이지 않지만. 감사!
nilton

7

특정 도구를 모르지만 Python과 해당 클래스 및 연산자를 사용하여 작은 스크립트를 작성하여 사용할 수 있습니다.

예를 들어 :

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

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

예, 좋은 대답입니다. 파이썬을 사용할 수 있다면 왜 awk를 사용합니까?
guettli

Python> import os
James Bowery

7

작은 콘솔 툴“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 자세한 내용은.


3

파일을 줄 집합으로보고 파일을 정렬하면이 comm있습니다.

파일을 (다중) 라인 세트로 보았고 라인이 정렬되지 않은 grep경우 차이와 교차를 수행 할 수 있습니다 (설정된 차이와 교차를 달성하지만 다중 세트의 개수는 고려하지 않음). 노동 조합은 단지 cat입니다.

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

2

여러 파일의 선 단위 조합, 교차, 차이 및 곱을 수행 할 수있는 Python 유틸리티를 만들었습니다. 이를 SetOp라고하며 PyPI ( here ) 에서 찾을 수 있습니다 . 구문은 다음과 같습니다.

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

1

나는 여러 곳에서 나에게 매우 유용한이 작업을 수행하는 작은 도구를 작성했습니다. UI가 연마되지 않았으며 매우 큰 파일의 성능 특성이 확실하지 않습니다 (전체 목록을 메모리로 읽어들이므로). 프로그램은 https://github.com/nibrahim/lines에 있습니다. 파이썬으로되어 있습니다. 를 사용하여 얻을 수 있습니다 pip install lines.

현재 두 파일의 합집합, 교집합, 차이 및 대칭 차이를 지원합니다. 입력 파일의 각 행은 세트의 요소로 취급됩니다.

또한 두 가지 추가 작업이 있습니다. 파일에서 빈 줄을 짜내고 두 번째는 (나에게 매우 유용했습니다) 파일을 살펴보고 유사한 문자열 세트로 나누는 것입니다. 일반적인 패턴과 일치하지 않는 목록에서 파일을 찾으려면 이것이 필요했습니다.

의견을 환영합니다.


0

파일 시스템은 파일 이름 (경로를 포함한 전체 파일 이름)을 고유 한 것으로 취급합니다.

운영?

a / 및 b /의 파일을 빈 디렉토리 c /에 복사하여 새로운 공용 집합을 얻을 수 있습니다.

like -e name및 loops 또는 find와 같은 파일 테스트를 통해 둘 이상의 디렉토리에 존재하는 파일을 확인하여 교차점 또는 차이를 얻을 수 있습니다.


1
파일 의 내용 을 세트의 요소 (예 : 한 줄에 하나의 요소)로 취급하고 파일 자체를 세트로 취급해야했습니다.
nilton

0

가장 좋은 답변은 : 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 연산을 작성할 수 있습니다!

어쨌든, 나는 그것이 매우 시원하다고 생각하며 완전히 확인해야합니다.


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옵니다 (또는 찾을 수없는 경우 0). 패턴으로 사용하기 e위해 제거 ( exact의 경우 $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]}

최소 / 최대 (10 진 정수 비교)

min=${${(no)array}[1]} max=${${(no)array}[-1]}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.