먼저 awk를 사용하여 마지막 줄을 처리하세요.

먼저 awk를 사용하여 마지막 줄을 처리하세요.

awk마지막 데이터 포인트를 기반으로 정규화하는 데 사용 하려는 데이터 파일이 있습니다 . 따라서 마지막 데이터 포인트에 먼저 접근하여 데이터를 정규화한 후 정상적으로 처리하고자 합니다.

두 번 사용되는 다음 방법은 tac작업을 수행하지만 아마도 필요한 것보다 더 복잡할 것입니다.

$ cat file
0 5
1 2
2 3
3 4
$ tac file | awk 'NR==1{norm=$2} {print $1, $2/norm}' | tac
0 1.25
1 0.5
2 0.75
3 1

내 질문은: awk만 사용하여 위의 결과를 얻을 수 있습니까?

나는 대답이 "아니요, awk는 파일을 한 줄씩 스캔합니다"라고 생각하지만 대안에 대한 제안에 열려 있습니다.

답변1

데이터 소스가 여러 번 읽을 수 있는 파일인 경우(즉, 스트림이 아닌 경우) 먼저 를 tail(1)사용하여 마지막 줄에서 원하는 데이터를 가져온 다음 awk에 전달하여 순차적으로 처리해야 합니다. tail파일 앞의 모든 데이터를 읽지 않고 마지막 줄을 읽으려면 파일 끝을 살펴봅니다.

awk -v norm=$(tail -n 1 file | cut -d' ' -f2) '{print $1, $2/norm}' file

이는 전체 파일이 버퍼 캐시에 맞지 않는(즉, 패스마다 한 번씩 디스크에서 두 번 읽어야 함을 의미함) 대용량 파일에 큰 이점이 될 것이며, 스캔하지 않고도 어느 정도 도움이 될 것입니다. 입력이 마지막 줄에 도달합니다. 더 작은 파일은 2단계 방법과 크게 다르지 않을 수 있습니다.

답변2

awk에서 2단계 솔루션으로 이 작업을 수행할 수 있습니다.

awk 'FNR == NR { n = $2; next } { print $1, $2/n }' infile infile

귀하의 awk 버전이 ENDFILE 블록(예: GNU awk 4+)을 지원하는 경우 다음을 수행할 수 있습니다.

awk 'ENDFILE { n = $2 } FNR != NR { print $1, $2/n }' infile infile

seek파일의 끝 부분을 먼저 보는 것이 더 효율적이라는 점에 유의하세요.캠의 대답.

설명하다

첫 번째 예는 $2로컬 행 카운터( ) FNR가 전역 행 카운터( )와 동일한 NR경우에만 계산 된다는 이전 내용을 기억하여 작동합니다. 명령 next은 다음 줄로 이동합니다. 이 경우 두 번째 인수가 구문 분석될 때만 마지막 블록이 평가되도록 합니다.

두 번째 예는 비슷한 논리를 가지고 있지만 입력 파일의 끝에 도달하면 평가되는 ENDFILE 블록을 활용합니다.

답변3

배열에 로드하고 거꾸로 읽을 수 있습니다.

awk '{x[i++]=$0} END{for (j=i-1; j>=0;) print x[j--] }'

이 작업을 더 효율적으로 수행할 수 있지만 이는 awk이것이 왜 올바른 도구가 아닌지를 보여줍니다. 가능한 경우 계속 사용하면 tacGNU tac은 일반적으로 작업에 사용되는 다양한 도구 중에서 가장 빠릅니다.

관련 정보