Awk printf 명령으로 출력을 올바르게 포맷하는 방법은 무엇입니까?

다음 파일이 있습니다.

echo filename dfT08r352|30.5|2010/06/01|2016/08/29|2281|6.24503764544832|74.9404517453799| zm00dr121|37|2008/03/05|2011/09/12|1285.95833333333|3.52076203513575|42.249144421629| ccvd00121|41.6|2008/03/05|2012/03/05|1461|4|48| sddf00121|39.6|2008/03/05|2012/09/10|1649.95833333333|4.51733972165184|54.208076659822| fttt00121|41|2008/03/05|2013/09/16|2020.95833333333|5.53308236367785|66.3969883641342| ghhyy0121|42.2|2008/03/05|2014/03/18|2203.95833333333|6.03410905772302|72.4093086926762| 

이 파일을 포맷하려고합니다. awk printf를 사용하여 다음과 같은 원하는 형식을 갖습니다.

  1. 동일한 필드 순서 유지 (왼쪽-> 오른쪽)
  2. 쉼표 “,”FS
  3. 모든 숫자가 4 자리 인 마지막 세 개의 필드 ($ 5, $ 6, $ 7) l 만 더 적은 경우 0123.12 또는 1234.10과 같은 점 뒤에 0과 2 자리 만있는 경우

다음 awk 명령을 작성했습니다.

awk -F"|" "{print $1","$2","$3","$4}{format = "%04.2f,%04.2f,%04.2f,"}{printf format, $5,$6,$7}" filename 

그러나 아래 출력에는 다음과 같은 문제가 있습니다.

  1. 정렬하지 않습니다 (왼쪽-> 오른쪽)

  2. 앞에 0이 없습니다.

    dfT08r352,30.5,2010/06/01,2016/08/29 2281.00,6.25,74.94,zm00dr121,37,2008/03/05,2011/09/12 1285.96,3.52,42.25,ccvd00121,41.6,2008/03/05,2012/03/05 1461.00,4.00,48.00,sddf00121,39.6,2008/03/05,2012/09/10 1649.96,4.52,54.21,fttt00121,41,2008/03/05,2013/09/16 2020.96,5.53,66.40,ghhyy0121,42.2,2008/03/05,2014/03/18 

누군가 내 실수가 무엇인지, 어떻게 해결해야하는지 알려 주실 수 있나요?

주석

  • 참고로, 각 쉼표를 인용하지 않고 쉼표로 구분하려면 'BEGIN {OFS=","}' 또는

—하지만 ' 더 광범위한 질문에 대한 답변은 없습니다.

답변

필드가 올바른 순서로되어 있지만 첫 번째 print 문은 줄 바꿈 (출력 레코드 구분 기호)을 추가하므로 데이터가 거기에 있지만 예기치 않게 래핑됩니다.

두 번째 문제는 “printf에게 너비 4를 사용하라고 명령하는 것입니다. 여기에는 소수점과 그 뒤의 두 자리가 포함되며 선행 숫자에 대해 하나만 남겨두고 패딩에 대해서는 없습니다. 너비로 5를 사용하여 데이터가 총 4 개까지 채워지도록합니다. 소수점 4 자리를 원하면 너비를 대신 7로 변경하세요.

이것은 제가 생각하는 것을 출력하는 프로그램으로 변경 한 것 중 가장 짧은 것입니다. want :

awk -F"|" "{ format = "%05.2f,%05.2f,%05.2f"; print $1","$2","$3","$4"," sprintf(format, $5,$6,$7)}" filename 

여러 { } 블록을 하나로 결합하고 print 문을 하나로 결합했습니다.

처음부터 awk 문을 작성하려면 다음과 같이 할 수 있습니다.

awk -v FS=\| -v OFS=, "{ $5=sprintf("%05.2f", $5); $6=sprintf("%05.2f", $6); $7=sprintf("%05.2f", $7); print $1,$2,$3,$4,$5,$6,$7}" filename 

입력 필드 구분자를 명시 적으로 설정합니다. , 출력 필드 구분 기호는 각 필드를 자체적으로 명시 적으로 변환 한 다음 원하는 필드를 OFS로 구분하여 인쇄합니다.

Comments

  • 와우 !!! 이것은 훌륭하고 많은 것을 배웁니다. 시간과 유익한 설명에 감사드립니다. 🙂 감사합니다!

답변

한 가지 방법 :

awk -F \| -v OFS=, "{ NF--; for(i = NF-2; i <= NF; i++) $i = sprintf("%07.2f", $i) } 1" filename 

댓글

  • @ Sato Katsura, Tnx는 완벽하게 작동합니다. 이해를 돕기 위해 스크립트에 설명해 주시기 바랍니다. 저는 Awk에서 처음입니다. ur 스크립트의이 부분에 대한 설명 만 필요합니다. {NF–; for (i = NF-2; i < = NF; i ++) $ i = sprintf (" % 07.2f ", $ i)} 1 '

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다