tags:

views:

805

answers:

6

Hi, I have the below awk command-line argument and it works aside from the fact it performs the print argument on the entire file (as expected). I would like it to just perform the formatting on the last 10 lines of the file (or any arbitrary number). Any suggestions are greatly appreciated, thanks!

I know one solution would be to pipe it with tail, but would like to stick with a pure awk solution.

awk '{print "<category label=\"" $13 " " $14 " " $15 "\"/>"}' foofile
A: 

There is loads of awk one liners in this text document, not sure if any of those will help.

This specifically might be what you're after (something similar anyway):

# print the last 2 lines of a file (emulates "tail -2")
awk '{y=x "\n" $0; x=$0};END{print y}'
Ian
A: 
awk '{ y=x "\n" $0; x=$0 }; END { print y }'

This is very inefficient: what it does is reading the whole file line by line only to print the last two lines.
Because there is no seek() statement in awk it is recommended to use tail to print the last lines of a file.

Robert Smith
+1  A: 

I don't think this can be tidily done in awk. The only way you can do it is to buffer the last X lines, and then print them in the END block.

I think you'll be better off sticking with tail :-)

Nick
+7  A: 

There is no need to be orthodox with a language or tool on the Unix shell.

tail -10 foofile | awk '{print "<category label=\"" $13 " " $14 " " $15 "\"/>"}'

is a good solution. And, you already had it.

Your arbitrary number can still be used as an argument to tail, nothing is lost;
solution does not lose any elegance.

nik
+1 For the Unix philosophy - little orthogonal tools that do their thing well.
Eclipse
A: 

Just for last 10 rows

awk 'BEGIN{OFS="\n"}
{
   a=b;b=c;c=d;d=e;e=f;f=g;g=h;h=i;i=j;j=$0
}END{    
    print a,b,c,d,e,f,g,h,i,j
}' file
ghostdog74
+2  A: 

Using ring buffers, this one-liner prints last 10 lines;

awk '{a[NR%10]=$0}END{for(i=NR+1;i<=NR+10;i++)print a[i%10]}'

then, you can merge "print last 10 lines" and "print specific columns" like below;

{
    arr_line[NR % 10] = $0;
}

END {
    for (i = NR + 1; i <= NR + 10; i++) {
        split(arr_line[i % 10], arr_field);
        print "<category label=\"" arr_field[13] " " \
                                   arr_field[14] " " \
                                   arr_field[15] "\"/>";
    }
}
Hirofumi Saito