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

0

1 Answer 1

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:

3
  • 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
    Commented Dec 21, 2016 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/…
    – user14755
    Commented Dec 21, 2016 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. Commented Dec 21, 2016 at 22:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .