Como EDITAR somente a última linha (ou qualquer número de linha específico) usando o comando awk?

1

I have a big multi columns file with #n number of records (lines). How I can only apply awk command in the last record or any specific records number (i.g. NR==4) or a range of lines (NR==[2-5])?

como exemplo no seguinte arquivo:

echo filename
30.5,2010/06/01,2016/08/29,2281.00,0006.25,0074.94
41.6,2008/03/05,2012/03/05,1461.00,0004.00,0048.00
39.6,2008/03/05,2012/09/10,1649.96,0004.52,0054.21
41.0,2008/03/05,2013/09/16,2020.96,0005.53,0066.40
42.2,2008/03/05,2014/03/18,2203.96,0006.03,0072.41
41.1,2008/03/05,2014/09/16,2385.96,0006.53,0078.39
43.1,2008/05/08,2014/09/16,/2322.00,/0006.36,/0076.29

I apply the following awk script to remove the / in any fields except the dates.

nawk -F, -v OFS=,  '{split($4,a,"/"); $4=sprintf("%06.2f", a[2]);split ($5,b,"/");$5=sprintf("%06.2f", b[2]);split($6,c,"/");$6=sprintf("%06.2f", c[2]); print $0}' filename 

Although it is correct for the last line but adversely impact on the other lines which do not have /. Following output :

output

30.5,2010/06/01,2016/08/29,000.00,000.00,000.00
41.6,2008/03/05,2012/03/05,000.00,000.00,000.00
39.6,2008/03/05,2012/09/10,000.00,000.00,000.00
41.0,2008/03/05,2013/09/16,000.00,000.00,000.00
42.2,2008/03/05,2014/03/18,000.00,000.00,000.00
41.1,2008/03/05,2014/09/16,000.00,000.00,000.00
43.1,2008/05/08,2014/09/16,2322.00,006.36,076.29


however, the expected correct output should be :

30.5,2010/06/01,2016/08/29,2281.00,0006.25,0074.94
41.6,2008/03/05,2012/03/05,1461.00,0004.00,0048.00
39.6,2008/03/05,2012/09/10,1649.96,0004.52,0054.21
41.0,2008/03/05,2013/09/16,2020.96,0005.53,0066.40
42.2,2008/03/05,2014/03/18,2203.96,0006.03,0072.41
41.1,2008/03/05,2014/09/16,2385.96,0006.53,0078.39
43.1,2008/05/08,2014/09/16,2322.00,0006.36,0076.29

So, how I can tell awk to only apply this in the last line or any specific line number(s)?

    
por Daniel 21.12.2016 / 22:15

1 resposta

4

Quando o awk processa o arquivo, a variável NR representa o número total de registros processados. Então você só precisa adicionar um padrão como

(NR == 5)

antes da sua ação

{split($4,a,"/");...

por exemplo,

(NR == 5){split($4,a,"/");...

para processar a linha 5.

Se você quiser processar apenas a linha última , poderá salvar a linha na ação padrão

{ save = $0; }

e processe essa linha na seção END . Mas você terá que fazer a divisão de campos lá ( $0 não se aplica mais):

END {split(whatever,a,"/");...

Para um intervalo, você usaria uma expressão mais complicada,

( NR >= 2 && NR <= 5 )

para selecionar as linhas de 2 a 5.

Leitura adicional:

por 21.12.2016 / 23:08