awk는 배열을 이전 줄의 배열과 비교합니다.

awk는 배열을 이전 줄의 배열과 비교합니다.

귀하의 도움에 감사드립니다. 데이터 파일에서 정보를 추출하고 있는데 어떤 경우에는 크기가 1TB를 초과합니다.

  • 각 줄의 변수는 공백으로 구분됩니다.
  • 파일당 줄당 변수 수는 고정되어 있습니다.
  • 오른쪽의 세 열은 항상 자연수입니다.
  • 줄은 항상 배열로 시작합니다
  • 배열에는 항상 파일당 고정된 수의 요소가 포함됩니다.
  • 배열은 1~5개의 요소를 포함할 수 있습니다.
  • 소스 데이터 파일이 올바르게 정렬되었습니다.

다음 예에서는 병렬 처리를 사용할 때 요소가 3개인 배열을 파일이나 블록의 다른 모든 배열과 비교합니다. 배열이 일치하면 오른쪽에서 두 번째 열을 추가하고 행을 병합합니다. 가장 오른쪽 열과 -2열이 새로 고쳐집니다.

g@grml # zcat googlebooks-eng-us-all-3gram-20120701-zz.gz | head
Z'Z . _END_     1840    1       1
Z'Z . _END_     1847    1       1
Z'Z . _END_     1850    1       1
Z'Z . _END_     1855    1       1
Z'Z . _END_     1856    1       1
Z'Z . _END_     1857    1       1
Z'Z . _END_     1860    1       1
Z'Z . _END_     1863    1       1
Z'Z . _END_     1865    1       1
Z'Z . _END_     1869    1       1



g@grml # zcat googlebooks-eng-us-all-3gram-20120701-zz.gz | parallel -k -q --pipe awk '{a[$1" "$2" "$3] +=$(NF-1)} END{for (i in a) print i, a[i]}' | head 
Zz_NOUN _NOUN_ , 98
zz _._ _PRT_ 120
ZZ or_CONJ _NOUN_ 122
ZZ_NOUN _DET_ _VERB_ 59
zz_DET _NOUN_ . 86
ZZ is_VERB reached 42
ZZ_NUM ^ ^ 65
ZZ _NOUN_ _VERB_ 3163
ZZ ,_. " 52
ZZ / _NUM_ 275

예제에서는 요소가 3개인 배열을 설명하지만 저는 1~5개의 요소가 포함된 배열을 사용하고 있습니다.

awk '{a[$1] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3" "$4] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3" "$3" "$5] +=$(NF-1)} END{for (i in a) print i, a[i]}'

awk가 파일이나 블록의 모든 배열과 모든 배열을 일치시키도록 하는 대신 awk에게 현재 배열을 이전 줄의 이전 배열과 비교하도록 어떻게 지시합니까?

감사해요

샘플 소스 파일.

wget --show-progress -cq http://storage.googleapis.com/books/ngrams/books/googlebooks-eng-us-all-3gram-20120701-zz.gz -O - | zcat

답변1

댓글에 URL로 제공되는 입력 데이터는 탭으로 구분됩니다. 이는 탭으로 구분된 첫 번째 필드를 일종의 "키"로 구문 분석하여 다른 행과 비교할 수 있음을 의미합니다. 사실 우리는아니요첫 번째 필드의 공백으로 구분된 단어에 주의해야 하지만 첫 번째 필드 전체를 단일 엔터티로 처리할 수 있습니다.

BEGIN { OFS = FS = "\t" }

{
    count = $(NF - 1)
    key = $1
}

key != previous {
    if (previous != "")
        print previous, sum

    sum = 0
}

{
    sum += count
    previous = key
}

END {
    if (previous != "")
        print previous, sum
}

프로그램 awk은 "count" 필드(두 번째 필드)를 구문 분석한 count다음 나중에 이전 행의 키와 비교할 수 있도록 첫 번째 필드를 "키"로 사용합니다. 이는 이 블록 BEGIN(입력 및 출력 구분 기호만 설정) 다음의 첫 번째 블록입니다 .

키가 이전 행의 키와 다르다면 이는 이제 다른 단어 집합을 보고 있다는 의미입니다. 이전 라인의 키와 합을 출력하고 합을 재설정합니다.

모든 행에 대해 해당 행의 개수에 합계를 더한 다음 업데이트합니다 previous(이제 행을 완료했으므로 key다음 행이 됩니다 previous).

마지막으로 데이터의 마지막 행 정보를 출력합니다.

를 사용하여 실행할 수 있습니다 awk -f script.awk inputfile.

"한 줄"로:

awk -F '\t' 'BEGIN{OFS=FS} {c=$(NF-1);k=$1} k!=p {if(p!="")print p,s;s=0} {s+=c;p=k} END {if(p!="") print p,s}' file

관련 정보