Domanda

I a having a sorted file with numeric values like

foo 2.3
bar 2.6
baz 4.7

and would like to have a one-liner which puts the percentile of a line into the last column, like

foo 2.3 0.3333
bar 2.6 0.6666
baz 4.7 1.0000

Thank you.

È stato utile?

Soluzione

I assume you mean percent of lines, for this you need to know the number of lines first.

Here's one way to do it as a two-pass solution with awk:

 awk 'FNR == NR { tot=NR; next } { printf( "%s %.4f\n", $0, FNR/tot) }' file file 

Output:

foo 2.3 0.3333
bar 2.6 0.6667
baz 4.7 1.0000

The first block is only active during FNR == NR i.e. the first pass. The second block takes care of the printing.

Other alternatives to determine length of file

Use NR-1 when starting second pass (FNR != NR):

awk 'FNR != NR { if(!tot) tot=NR-1; printf( "%s %.4f\n", $0, FNR/tot) }' file file

Use wc before running awk:

awk -v tot=$(wc -l < file) '{ printf( "%s %.4f\n", $0, FNR/tot) }' file

Altri suggerimenti

$ awk 'c=NR-FNR{printf "%s %.4f\n",$0,FNR/c}' file file
foo 2.3 0.3333
bar 2.6 0.6667
baz 4.7 1.0000

even though @thor solution is good, there is no need to traverse the file twice.Instead we can do it inside the memory itself.

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

tested:

> cat temp
foo 2.3
bar 2.6
baz 4.7
> awk '{a[NR]=$0;}END{for(i=1;i<=NR;i++)print a[i],i/NR;}' temp
foo 2.3 0.333333
bar 2.6 0.666667
baz 4.7 1

if you are specific about the precision then use below:

> awk '{a[NR]=$0;}END{for(i=1;i<=NR;i++)printf("%s %0.4f\n",a[i],i/NR);}' temp
foo 2.3 0.3333
bar 2.6 0.6667
baz 4.7 1.0000
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top