파일에서 데이터를 추출하여 큰 고정 너비 테이블로 구성하고 싶습니다. 테이블에는 여러 개의 열이 있을 것으로 예상됩니다. 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
정규식을 사용합니다.FS
a
for
모든 필드를 (자동으로) 반복합니다 .printf
모든 필드는 동일한 형식으로 인쇄됩니다 .- 그리고 마지막으로
print
줄바꿈 문자가 줄 끝에 배치됩니다.
이는 필드 수에 관계없이, 심지어 필드 수가 다른 행에서도 작동하므로 더욱 유연합니다. 그리고 단 하나의 언어로만 수행할 수 있습니다(이해하고 유지하기가 더 쉽습니다).
심지어:
$ awk 'for(i=1;i<=NF;i++){ printf("%-5s",$i) }; print ""}' infile
%-5.5s
5자보다 긴 필드를 잘라내 도록 형식을 변경할 수 있습니다 .
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