60개의 대용량 파일을 비교하여 모든 파일에 공통되는 라인만 출력

60개의 대용량 파일을 비교하여 모든 파일에 공통되는 라인만 출력

나는 각각 약 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 { ... }각 파일의 시작 부분에서 실행

  • !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개의 스레드로 분할될 수 있습니다.

관련 정보