거대한 구분 텍스트 파일에서 열 추출

거대한 구분 텍스트 파일에서 열 추출

33GB 파이프로 구분된 플랫 파일이 있습니다.

첫 번째 열과 20번째 열이 조건을 충족하는 파일에서 특정 열을 추출해야 합니다.

다음 코드를 사용하여 입력 파일을 처리합니다.

awk -F"|" '('$1~/^BL|^FR|^GF|^GP|^MC|^MF|^MQ|^NC|^PF|^PM|^RE|^TF|^WF|^YT/&&$20=="TRUE"') {print $0}' <input file> | cut -d'|' -f1-3,6,10,11,13,19,20 >> <output file>

$1$20입력 파일의 열 위치입니다 .

이 코드는 잘 작동합니다. 그러나 데이터를 추출하는 데 거의 1.5시간이 걸립니다. 파일을 더 빠르게 처리하는 방법이 있나요?

답변1

을 사용해 보세요 grep.

(
  export LC_ALL=C
  grep -E '^(BL|FR|[GMTW]F|GP|M[CQ]|NC|PM|RE|YT)([^|]*\|){19}TRUE(\||$)' |
    cut -d'|' -f1-3,6,10,11,13,19,20
)

@don_crissti가 제안한 것처럼 모든 행에 20개 이상의 필드가 포함되어 있다고 가정하면 먼저 잘라내기를 시도해 볼 수도 있습니다. 이렇게 하면 각 행의 필드 수와 길이, 일치하는 행의 비율에 따라 더 나은 성능을 얻을 수 있습니다.

(
  export LC_ALL=C
  cut -d'|' -f1-3,6,10,11,13,19,20 |
    grep -xE '(BL|FR|[GMTW]F|GP|M[CQ]|NC|PM|RE|YT).*\|TRUE'
)

답변2

마크 해볼까? 버전 1.34 이상을 사용하세요. 일부 사람들의 예에서는 대용량 파일을 처리하는 작업 속도가 8배 빨라질 수 있습니다.

https://brenocon.com/blog/2009/09/dont-mawk-awk-the-fastest-and-most-elegant-big-data-munging-언어/

현재 성능과 절대적인 비교를 위해 이 작업은 1GB를 처리하는 데 1분(mawk 사용)이 걸렸습니다. Java(JIT) 코드를 사용하려는 시도는 더 빠르지 않습니다.

또한 UTF-8 지원이 추가된 후 많은 유틸리티의 성능이 저하된 것으로 보입니다. ㅏ구글 검색이는 최소한 일부 버전의 awk에 매우 눈에 띄는 영향을 미친다는 것을 보여줍니다. 환경 변수 LC_ALL=C(예: LC_ALL=C awk ...)를 사용하여 실행해 보십시오.

답변3

최소한 다음을 제거할 수 있습니다 cut.

awk -F '|' 'BEGIN { OFS=FS } $20 == "TRUE" && /^(BL|FR|GF|GP|MC|MF|MQ|NC|PF|PM|RE|TF|WF|YT)/ { print $1,$2,$3,$6,$10,$11,$13,$19,$20 }' indata >outdata

이것이 더 빠르게 실행되는지는 모르겠지만 각 행을 필드로 두 번 이상 나눌 필요가 없습니다.

awk필터링 노력을 줄이기 위해 먼저 올바른 열을 제거해 볼 수도 있습니다 .

cut -d '|' -f 'columnspec' indata | awk -F '|' 'BEGIN { OFS=FS } $20 == "TRUE" && /^(BL|FR|GF|GP|MC|MF|MQ|NC|PF|PM|RE|TF|WF|YT)/ { print }' >outdata

또 다른 접근 방식은 파일을 관리 가능한 청크로 분할하고 청크를 병렬로 필터링한 다음 결과를 연결하는 것입니다. splitUnix 매뉴얼을 참고하세요 . 수백 개의 파일을 생성한다면 분할 플래그를 사용해야 할 수도 있지만 -a, 데이터 내에서 파일의 라인 수를 세어 약 10개 정도의 파일로 분할하는 것을 권장합니다.

답변4

Python의 줄별 접근 방식 사용

다음 스크립트는 첫 번째 열이 정의된 문자열과 동일한 경우 행의 모든 ​​열 집합을 반환합니다. 필수 일치 항목과 반환할 열은 스크립트를 실행하기 위한 매개 변수입니다. 한 가지 예:

python3 /path/to/script.py /path/to/file.txt monkey 3 12 > output.txt

첫 번째 열이 "monkey"와 같으면 file.txt에 있는 각 행의 열 0, 2, 11이 반환됩니다(첫 번째 열은 0임).

타이밍

30,000,000줄의 수 기가바이트 파일에서 스크립트는 10년 이상 된 내 컴퓨터에서 1분 이내에 작업을 완료했습니다. 스크립트가 읽고 처리되기 때문에각 라인, 소비되는 시간이 다소 선형적이며 스크립트가 명령보다 훨씬 빠르게 작업을 수행한다고 가정할 수 있습니다.

스크립트

#!/usr/bin/env python3
import sys

s = sys.argv[2]; cols = [int(n) for n in sys.argv[3:]]

with open(sys.argv[1]) as src:
    for l in src:
        l = l.split("|"); match = l[0].strip()
        if match == s:
            print(match, " ".join(list(l[i].strip() for i in cols)))

사용하는 방법

  1. 스크립트를 빈 파일에 복사하고 다른 이름으로 저장하세요.get_cols.py
  2. 다음 매개변수를 사용하여 실행하세요.

    • 소스 파일
    • 첫 번째 열(문자열)에 대한 필수 일치 항목
    • 출력할 열

    예를 들어:

    python3 /path/to/get_cols.py Germany 2 12 > output.txt
    

그게 다야

관련 정보