Tenho o seguinte arquivo:
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|
Estou tentando formatar este arquivo usando awk printf para ter o seguinte formato desejado:
- manter a mesma ordem dos campos (esquerda -> direita)
- ter vírgula “,” FS
- apenas para l ast três campos ($ 5, $ 6, $ 7) tendo todos os números com 4 dígitos, se menos tiver um zero à esquerda e apenas 2 dígitos após o ponto, como 0123,12 ou 1234,10
Eu escrevi o seguinte comando awk
awk -F"|" "{print $1","$2","$3","$4}{format = "%04.2f,%04.2f,%04.2f,"}{printf format, $5,$6,$7}" filename
entretanto, a saída abaixo tem os seguintes problemas:
-
não está em ordem (esquerda -> direita)
-
não tenha o zero à esquerda
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
Alguém pode me informar qual é o meu erro e como corrigi-lo?
Comentários
—mas isso não ' responde à sua pergunta mais ampla.
Resposta
Você tem os campos na ordem certa, mas sua primeira instrução de impressão adiciona uma nova linha (separador de registro de saída), de modo que seus dados estão lá, mas apenas agrupados inesperadamente.
O segundo problema é que você está dizendo ao printf para usar uma largura de 4; isso inclui o ponto decimal e os dois dígitos após ele, deixando apenas um para o dígito inicial e nenhum para qualquer preenchimento. Tente usar 5 como largura, para que seus dados sejam preenchidos com até quatro números totais. Se você quiser 4 dígitos antes da vírgula decimal, altere a largura para 7 em vez disso.
Esta é a mudança mais curta que fiz em seu programa para algo que produz o que eu acho que você querer:
awk -F"|" "{ format = "%05.2f,%05.2f,%05.2f"; print $1","$2","$3","$4"," sprintf(format, $5,$6,$7)}" filename
Combinei vários blocos { }
em um e também combinei as instruções de impressão em um.
Se eu fosse escrever sua instrução awk do zero, eu poderia fazer algo assim:
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
Ele define explicitamente o separador de campo de entrada , o separador de campo de saída, converte explicitamente cada um dos campos por conta própria e, em seguida, imprime os campos desejados, com o OFS separando-os.
Comentários
- Uau !!! Isso é ótimo e eu aprendo muito. Agradeço muito seu tempo e sua descrição informativa 🙂 Melhor!
Resposta
Uma maneira de fazer isso:
awk -F \| -v OFS=, "{ NF--; for(i = NF-2; i <= NF; i++) $i = sprintf("%07.2f", $i) } 1" filename
Comentários
- @ Sato Katsura, Tnx muito funciona perfeitamente. Peço a você que explique seus scripts para entendê-los! Eu sou novo no Awk. Só precisa da explicação para esta parte do seu script: {NF–; para (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '
'BEGIN {OFS=","}'
ou apenas