awk는 한 파일에서 헤더를 읽고 분할하여 다른 파일에서 사용합니다.

awk는 한 파일에서 헤더를 읽고 분할하여 다른 파일에서 사용합니다.

나는 열 166 이후의 열 헤더를 가져와 이를 각 후속 행에 인쇄하는 awk 스크립트를 사용하고 있습니다.

전임자.

col165    col166    col167
a         1         2
b         3         4
c         5         6

이 되다--

col165    col166    col167
a         col166|1         col167|2
b         col166|3         col167|4
c         col166|5         col167|6

그런데 제가 작업하고 있는 파일은 꽤 크며(약 160만 줄) 처리하는데 약 1.5시간이 걸립니다.

프로세스 속도를 높이기 위해 대용량 파일을 100,000개 라인으로 분할한 다음 gnu를 사용하여 parallel각 파일을 개별적으로 처리하는 방법을 생각했습니다. 그러나 파일의 헤더를 가져와 헤더를 가져오는 데 사용하는 스크립트에 문제가 발생했습니다. 헤더를 지정하기 위해 다른 파일을 사용하고 싶습니다. 그렇지 않으면 각 분할 파일에 헤더를 추가해야 합니다(그 자체로는 번거로워 보입니다).

내가 사용하는 코드는 -

awk 'BEGIN { FS="\t";OFS="\t" };
     NR == 1 { split($0, headers); print; next }
     {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' input > output

column_headers파일을 사용하여 제목을 지정 하고 싶습니다 . 가능합니까?

다음 코드를 시도했지만 작동하지 않으며 코드가 올바른지 확실하지 않습니다.

awk -v head='$(cat column_headers)' 'BEGIN{ FS="\t";OFS="\t" };
        NR == 1 { split($head, headers); print; next }
        {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' input > output

내가 뭔가 잘못하고 있는 것 같은 느낌이 들지만 무엇인지 잘 모르겠습니다. 제가 받을 수 있는 어떤 도움이라도 감사하겠습니다.

편집: 감사합니다. 실제로 장기적인 범인이었던 체인의 또 다른 명령을 놓쳤습니다.

@Ole Tange가 언급했듯이 명령을 사용했지만 약간 수정했습니다.

time cat input_1|parallel -k -q -j 24 --tmpdir tmp/ --block 900M --pipe awk -f culprit_script > output

스크립트는 기본적으로 각 필드를 분할하고 값에 따라 제거/유지합니다.

첫 번째 명령을 실행하는 데 약 15~20분이 걸렸고, 두 번째 스크립트는 한 시간 남짓 걸렸습니다. 병렬성과 24스레드를 활용하여 7분만에 완료! 첫 번째 명령에도 병렬성을 사용할 것 같아요 :P

모든 분들의 의견과 제안에 감사드립니다!

답변1

실제로 답변은 아니지만 너무 크고 서식이 필요하므로 주석이 될 수 없으므로 ...

1.6M은 많은 행 수가 아닙니다. 말씀하신 대로 시간당 100만 행이 표시됩니다.대규모로느리다면 분당 100만 행이 더 합리적입니다. 예를 들어 다음 스크립트를 실행하여 한 줄에 300개의 열이 있는 1,600,000줄의 파일을 만들었습니다.

$ awk -v n=1600000 -v c=300 -v OFS='\t' 'BEGIN{for (j=1;j<=c;j++) printf "col%s%s",j,(j<c?OFS:ORS); for (i=1;i<=n;i++) for (j=1;j<=c;j++) printf "%s%s",j,(j<c?OFS:ORS)}' > file

그런 다음 정기적으로 스크립트를 실행하여 문제의 파일을 변환합니다.

$ time awk 'BEGIN{FS=OFS="\t"} NR==1{split($0, headers); print; next} {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' file > out

real    1m22.569s
user    1m17.971s
sys     0m4.359s

따라서 실행 시간은 1.5시간이 아닌 약 82초입니다.

답변2

GNU Parallel의 경우 다음과 같습니다.

#!/bin/bash

do_block() {
    awk 'BEGIN{FS=OFS="\t"}
     NR==1{split($0, headers); next}
     {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1'
}
export -f do_block

# Non-parallel version
cat file | head -n1 > out1
time cat file | do_block >> out1

# Parallel version
cat file | head -n1 > out2
time parallel -k --pipepart --block -30 -a file --header : do_block >> out2

내 4코어 CPU에서는 병렬 버전이 약 3배 더 빠릅니다.

관련 정보