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])?

as an example in the following file:

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)?

  • please provide an example of wanted or correct output and example of actual or incorrect output – lesmana Dec 21 '16 at 21:37
  • @ lesmana Done! – Daniel Dec 21 '16 at 21:55
5

As awk processes the file, the variable NR represents the total number of records processed. So you need only add a pattern such as

(NR == 5)

before your action

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

e.g.,

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

to process line 5.

If you want to process the last line only, then you can save the line in the default action

{ save = $0; }

and process that line in the END section. But you'll have to do field splitting there ($0 no longer applies):

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

For a range, you would use a more complicated expression,

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

to select rows 2 through 5.

Further reading:

  • Thanks a lot for the information. Can you please tell me two more things: How does it work in terms of the range of records? for instance lines 5 till 15? In addition, can you please write the whole awk script for the last line for me. Tnx – Daniel Dec 21 '16 at 22:22
  • IIRC - END containing the last row doesn't work for all (most but not all) versions of awk. gnu.org/software/gawk/manual/html_node/… – DarkHeart Dec 21 '16 at 22:23
  • 1
    You should always get END, and if (as noted) save the value in the default action, that's available for use in the END action. – Thomas Dickey Dec 21 '16 at 22:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.