Print line when closest number if found

so i have a code that identifies which value is the closest to a value provided by the user.

awk -F"," -v c=${COLUMN} -v t=${USTIME} '{a[NR]=$c}END{
        asort(a);d=a[NR]-t;d=d<0?-d:d;v = a[NR]
        for(i=NR-1;i>=1;i--){
                m=a-t;m=m<0?-m:m
                if(m<d){
                    d=m;v=a
                }
        }
        print v
}' data.file

content of data file:

blah1,blah1,1453745100,blah1,blah1,blah1
blah2,blah2,1453745196,blah2,blah2,blah2
blah3,blah3,1453745296,blah3,blah3,blah3
blah4,blah4,1453745396,blah4,blah4,blah4

right now, this code only outputs the value that it finds to be closest. but i want it to output the entire line from which that value is found.

so, say, this code outputted 1453745196. Instead of that, i want it to output

blah2,blah2,1453745196,blah2,blah2,blah2

Quick hack:

awk -F"," -v c=${COLUMN} -v t=${USTIME} '{a[NR]=$c; b[NR]=$0}END{
        asort(a);d=a[NR]-t;d=d<0?-d:d;v = a[NR]; r=b[NR]
        for(i=NR-1;i>=1;i--){
                m=a-t;m=m<0?-m:m
                if(m<d){
                    d=m;v=a; r=b
                }
        }
        print r
}' data.file

Unfortunately, both my awk versions don't have the sort function; with that, this would be even simpler. Try

awk -F, -vc=3 -vt=1453745256 '{print ($c-t)*($c-t), $0}' file | sort -n | head -1 | cut -d" " -f2-
blah3,blah3,1453745296,blah3,blah3,blah3

---------- Post updated 26-01-16 at 07:18 ---------- Previous update was 25-01-16 at 22:52 ----------

Can't test this one, so please report back. According to man gawk , asorti(s) provides sorting by the indices. Try (untested)

awk -F, -vc=3 -vt=1453745256 '{S[$c-t)*($c-t)] = $0} END {asorti(S); print S[1]}' file
1 Like

I might be mistaken but to me the problem seems to be quite simply to solve (unfortunately my awk skills are not the best, you can perhaps shake out an implementation that puts whatever i could come up with to shame in an instant), here is the algorithm:

read first line and store:
          - the line itself
          - the number (or the difference between the number and the user provided value)

read the following line and
          - calculate the difference between its number and the user value
          IF this difference is smaller than the stored one
               - replace the stored line data with the current lines data
          FI
until end of file

You do not need to sort the file at all, just cycle through it once. If the user provided value can be higher or lower than the values in the file you of course need to calculate the absolute value of the difference instead of the difference itself (multiply by -1 if lower than zero).

I hope this helps.

bakunin

1 Like