거대한 파일에서 많은 수의 패턴을 Grep합니다.

거대한 파일에서 많은 수의 패턴을 Grep합니다.

매일 약 200,000줄씩 늘어나는 파일이 있는데, 모두 다음과 같이 세 줄로 이루어진 덩어리로 구성되어 있습니다.

1358726575123       # key
    Joseph Muller   # name
    carpenter       # job
9973834728345
    Andres Smith
    student
7836472098652
    Mariah Anthony
    dentist

이제 약 10,000개의 주요 패턴을 추출한 또 다른 파일이 있습니다 1358726575123. 그런 다음 for이러한 패턴으로 루프를 실행하고 첫 번째 파일과 비교해야 합니다. 파일에 이러한 패턴이 포함되어 있지 않으면 추가 처리를 위해 세 번째 파일에 패턴을 저장합니다.

for number in $(grep -o '[0-9]\{12\}' file2); do  # finds about 10.000 keys
     if ! grep -q ^$number$ file1; then           # file1 is a huge file
         printf "$number\n" >>file3               # we'll process file3 later
     fi
done

예제 코드는 큰 파일을 10,000번 grep합니다. 저는 이 루프를 대략 10,000번 실행합니다.1분에 한 번, 하루 종일.

대용량 파일이 계속해서 커지는데, 이 모든 것을 더 빠르게 만들고 일부 CPU를 절약하려면 어떻게 해야 합니까? 키별로 파일을 정렬하거나(그렇다면 어떻게?) 일반 텍스트 대신 데이터베이스를 사용하는 것이 도움이 될지 궁금합니다.

답변1

물론 문제는 큰 파일에 대해 grep을 10,000번 실행한다는 것입니다. 두 파일을 한 번만 읽어야 합니다. 스크립팅 언어를 사용하지 않으려면 다음을 수행할 수 있습니다.

  1. 파일 1에서 모든 숫자를 추출하고 정렬합니다.
  2. 파일 2에서 모든 숫자를 추출하고 정렬합니다.
  3. comm두 번째 목록에 있는 내용만 얻으려면 정렬된 목록을 실행하세요.

이 같은:

$ grep -o '^[0-9]\{12\}$' file1 | sort -u -o file1.sorted
$ grep -o  '[0-9]\{12\}'  file2 | sort -u -o file2.sorted
$ comm -13 file1.sorted file2.sorted > file3

바라보다 man comm.

로그 파일과 같은 대용량 파일을 매일 자를 수 있다면 정렬된 숫자의 캐시를 유지할 수 있으며 매번 구문 분석할 필요가 없습니다.

답변2

awk이 답변은 게시된 답변을 기반으로 합니다.포통.. 동일한 상황에서 이 방법(내 시스템에서)
보다 두 배 빠릅니다.comm600만 행메인 파일과10000키... (이제 FNR, NR을 사용하도록 업데이트됨)

현재 시스템보다 빠르며 awk귀하와 귀하의 컴퓨터에 약간의 여유 공간을 제공하지만 데이터 처리가 설명만큼 집중적일 경우 전용 데이터베이스로 전환하면 최상의 전체 결과를 얻을 수 있다는 점에 유의하십시오. SQLite, MySQL...


awk '{ if (/^[^0-9]/) { next }              # Skip lines which do not hold key values
       if (FNR==NR) { main[$0]=1 }          # Process keys from file "mainfile"
       else if (main[$0]==0) { keys[$0]=1 } # Process keys from file "keys"
     } END { for(key in keys) print key }' \
       "mainfile" "keys" >"keys.not-in-main"

# For 6 million lines in "mainfile" and 10 thousand keys in "keys"

# The awk  method
# time:
#   real    0m14.495s
#   user    0m14.457s
#   sys     0m0.044s

# The comm  method
# time:
#   real    0m27.976s
#   user    0m28.046s
#   sys     0m0.104s

답변3

예, 반드시 데이터베이스를 사용하세요. 이러한 유형의 작업을 위해 설계되었습니다.

답변4

데이터가 너무 많으면 데이터베이스로 전환해야 합니다. 동시에 적절한 성능에 근접하기 위해 해야 할 일은 file1각 키를 개별적으로 검색하지 않는 것입니다. grep한 번에 제외되지 않은 모든 키를 추출하려면 한 번 실행하세요 . 키가 포함되지 않은 행도 반환 되므로 grep필터링됩니다.

grep -o '[0-9]\{12\}' file2 |
grep -Fxv -f - file1 |
grep -vx '[0-9]\{12\}' >file3

( -Fx문자 그대로 전체 행을 검색하는 것을 의미합니다. -f -표준 입력에서 패턴 목록을 읽는 것을 의미합니다.)

관련 정보