나는 각각 약 10,000줄을 포함하는 60개의 파일을 가지고 있습니다. 각 줄에는 문자열이 포함되어 있습니다.
모든 파일에 공통되는 문자열을 찾고 싶습니다.
정확히 일치하는 항목이 있어야 하므로 전체 행을 비교합니다.
답변1
이 시도,
awk '
BEGINFILE{fnum++; delete f;}
!f[$0]++{s[$0]++;}
END {for (l in s){if (s[l] == fnum) print l}}
' files*
설명하다:
BEGINFILE { ... }
각 파일의 시작 부분에서 실행fnum++
파일 카운터 늘리기delete f
배열 삭제이것은 사용됩니다파일당 중복 라인 필터링(posix 호환 솔루션 링크 참조)
!f[$0]++ { ... }
파일에서 첫 번째 줄에서만 실행(f[$0]
0(false)인 경우)s[$0]++
행 카운터를 증가시킵니다.
END { ... }
지난번에 실행for (l in s){if (s[l] == fnum) print l}
라인을 반복하고 파일 수와 동일한 횟수로 발생하는 각 라인을 인쇄합니다.
600,000행은 메모리에 충분합니다. 그렇지 않으면 s
블록보다 작은 fnum
모든 것을 제거할 위험이 있습니다 BEGINFILE{...}
.
답변2
Bash의 병렬 버전. 메모리보다 큰 파일에서는 작동합니다.
export LC_ALL=C
comm -12 \
<(comm -12 \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 1) <(sort 2);) <(comm -12 <(sort 3) <(sort 4););) \
<(comm -12 <(comm -12 <(sort 5) <(sort 6);) <(comm -12 <(sort 7) <(sort 8);););) \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 9) <(sort 10);) <(comm -12 <(sort 11) <(sort 12););) \
<(comm -12 <(comm -12 <(sort 13) <(sort 14);) <(comm -12 <(sort 15) <(sort 16););););) \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 17) <(sort 18);) <(comm -12 <(sort 19) <(sort 20););) \
<(comm -12 <(comm -12 <(sort 21) <(sort 22);) <(comm -12 <(sort 23) <(sort 24);););) \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 25) <(sort 26);) <(comm -12 <(sort 27) <(sort 28););) \
<(comm -12 <(comm -12 <(sort 29) <(sort 30);) <(comm -12 <(sort 31) <(sort 32);););););) \
<(comm -12 \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 33) <(sort 34);) <(comm -12 <(sort 35) <(sort 36););) \
<(comm -12 <(comm -12 <(sort 37) <(sort 38);) <(comm -12 <(sort 39) <(sort 40);););) \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 41) <(sort 42);) <(comm -12 <(sort 43) <(sort 44););) \
<(comm -12 <(comm -12 <(sort 45) <(sort 46);) <(comm -12 <(sort 47) <(sort 48););););) \
<(comm -12 \
<(comm -12 \
<(comm -12 <(comm -12 <(sort 49) <(sort 50);) <(comm -12 <(sort 51) <(sort 52););) \
<(comm -12 <(comm -12 <(sort 53) <(sort 54);) <(comm -12 <(sort 55) <(sort 56);););) \
<(cat <(comm -12 <(comm -12 <(sort 57) <(sort 58);) <(comm -12 <(sort 59) <(sort 60););) ;);););
파일이 정렬되어 있으면 sort
.cat
답변3
For, 레이블이 지정된 배열에서 zsh
배열 교차 연산자를 사용합니다.${a:*b}
고유한플래그(또한 $(<file)
ksh 연산자 및 f
매개변수 확장 플래그를 사용하여 개행을 분할함):
#! /bin/zsh -
typeset -U all list
all=(${(f)"$(<${1?})"}); shift
for file do
list=(${(f)"$(<$file)"})
all=(${all:*list})
done
print -rC1 -- $all
(스크립트는 파일 목록을 인수로 사용하며 빈 줄은 무시됩니다.)
답변4
그리고 join
:
cp a jnd
for f in a b c; do join jnd $f >j__; cp j__ jnd; done
세 개의 파일 a, b, c에 숫자(1-6, 3-8, 5-9)만 있습니다. 이는 세 가지 모두에 공통되는 두 줄(숫자, 문자열)입니다.
]# cat jnd
5
6
cp
특히 그 사이에는 우아하거나 효율적이지 않습니다 . 그러나 쉽게 병렬로 작동할 수 있습니다. 파일 하위 그룹( for f in a*
)을 선택하고 파일에 고유한 이름을 지정하면 여러 하위 그룹을 한 번에 실행할 수 있습니다. 여전히 결과를 연결해야 합니다... - 64개의 파일에 대해 각각 8개의 파일을 연결하는 8개의 스레드가 있고 연결된 나머지 8개의 파일은 다시 4개의 스레드로 분할될 수 있습니다.