고정 너비 열이 있는 테이블을 생성하기 위해 awk에서 배열 호출

고정 너비 열이 있는 테이블을 생성하기 위해 awk에서 배열 호출

파일에서 데이터를 추출하여 큰 고정 너비 테이블로 구성하고 싶습니다. 테이블에는 여러 개의 열이 있을 것으로 예상됩니다. 30개의 열이 있다고 가정해 보겠습니다. 이 테이블을 생성하기 위해 기존 명령줄을 사용했다면 다음과 유사한 awk매우 긴 명령줄을 작성해야 합니다 .awk

awk '{printf "%-5s  %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s\n", $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30}'

이 선형을 더 짧게 만드는 방법이 있습니까? 예를 들어 위의 긴 명령에서 배열을 구현하려고 합니다. 배열은 awk다음과 같이 각 열을 개별적으로 정의하는 대신 생성하려는 열의 수와 너비를 알려줍니다.

awk 'BEGIN {for i in {1..30}; do echo %-5s\n print i}

awk여러 개의 고정 너비 열을 생성하기 위해 이 방법을 내부적으로 올바르게 구현하려면 어떻게 해야 합니까 ?

답변1

한 번에 한 필드씩 루프 내에서 인쇄 자체를 수행할 수 있습니다.

awk '{for(i=1;i<=NF;i++) { printf "%-5s",$i } ; printf("\n"); }'

여러 줄이 하나로 병합되는 것을 방지하려면 루프 뒤에 개행 문자를 인쇄해야 합니다.

예를 들어

echo a b c 32 87 x5 | awk '{for(i=1;i<=NF;i++) { printf "%-5s",$i } ; printf("\n"); }'
a    b    c    32   87   x5  

답변2

단계적으로 몇 가지 변수를 구축할 수 있지만 권장하지는 않습니다(bash의 예).

$ printf -v l '%s ' {1..30}           # list of numbers to use
$ printf -v a '%.0s%%-5s ' $l         # make a string of repeated "%-5s"
$ printf -v b ',$%s' $l               # make string of field numbers as "$1,$2.."
$ awk -va="$a" '{printf a "\n"'"$b"'}' infile4

하지만 awk에서도 이 모든 작업을 수행할 수 있습니다.

$ awk '{split($0,a); for(i in a){printf "%-5s", $i}; print ""}' infile
  • in은 행을 필드로 분할하고 각 값을 배열에 넣는 데 사용된 것과 split동일한 awk정규식을 사용합니다.FSa
  • for모든 필드를 (자동으로) 반복합니다 .
  • printf모든 필드는 동일한 형식으로 인쇄됩니다 .
  • 그리고 마지막으로 print줄바꿈 문자가 줄 끝에 배치됩니다.

이는 필드 수에 관계없이, 심지어 필드 수가 다른 행에서도 작동하므로 더욱 유연합니다. 그리고 단 하나의 언어로만 수행할 수 있습니다(이해하고 유지하기가 더 쉽습니다).

심지어:

$ awk 'for(i=1;i<=NF;i++){ printf("%-5s",$i) }; print ""}' infile

%-5.5s5자보다 긴 필드를 잘라내 도록 형식을 변경할 수 있습니다 .

awk의 printf는 분해된 문자를 두 문자로 잘못 계산합니다. 유니코드 클러스터 대신 유니코드 코드 포인트(일반적인 문제)를 계산하는 것 같습니다.


편집하다 댓글에서 다음 추가 질문에 답하세요.

열 27을 정의하는 테이블의 행을 합산합니다.

필요한 코드를 추가하면 됩니다:

$ awk '{split($0,a); 
        sum=sum+a[27];
        for(i in a){ printf "%-5s", $i };
        print ""
       } END {
       print "Sum of column 27 is =", sum }
      ' infile

관련 정보