bash, find nearest next value, forward and backward

余生颓废 提交于 2019-12-01 12:44:21

Try this:

$ cat tst.awk
{
    if ($fld > tgt) {
        del = $fld - tgt
        if ( (del < minGtDel) || (++gtHit == 1) ) {
            minGtDel = del
            minGtVal = $fld
        }
    }
    else if ($fld < tgt) {
        del = tgt - $fld
        if ( (del < minLtDel) || (++ltHit == 1) ) {
            minLtDel = del
            minLtVal = $fld
        }
    }
    else {
        minEqVal = $fld
    }
}
END {
    print (minGtVal == "" ? "NaN" : minGtVal)
    print (minLtVal == "" ? "NaN" : minLtVal)
    print (minEqVal == "" ? "NaN" : minEqVal)
}

.

$ awk -v fld=4 -v tgt=11.6667 -f tst.awk file
12.3333
11.2222
NaN

$ awk -v fld=6 -v tgt=62.9997 -f tst.awk file
63.4444
62.3333
NaN

$ awk -v fld=6 -v tgt=62.3333 -f tst.awk file
63.4444
61.2222
62.3333

For the first part:

awk -v v1="11.6667" '$4>v1 {print $4;exit}' file
12.3333

And second part:

awk -v v2="62.9997" '$6>v2 {print p;exit} {p=$6}' file
62.3333

Both in one go:

awk -v v1="11.6667" -v v2="62.9997" '$4>v1 && !p1 {p1=$4} $6>v2 && !p2 {p2=p} {p=$6} END {print p1,p2}' file
12.3333 62.3333

I don't know if this is what you're looking for, but this is what I came up with, not knowing awk:

#!/bin/sh

IFSBAK=$IFS
IFS=$'\n'

best=

for line in `cat $1`; do
    IFS=$' \t'
    arr=($line)


    num=${arr[5]}
    [[ -z $best ]] && best=$num

    if [ $(bc <<< "$num < 62.997") -eq 1 ]; then 
        if [  $(bc <<< "$best < $num") -eq 1 ]; then
            best=$num
        fi
    fi

    IFS=$'\n'
done

IFS=$IFSBAK
echo $best

If you want, you can add the column and the input value 62.997 as paramters, I didn't to demonstrate that it would look for specifically what you want.

Edited to remove assumption that file is sorted.

You solution looks unnecessarily complicated (storing a whole array and sorting it) and I think you would see the bash solution if you re-thought your awk.

In awk you can detect the first line with

FNR==1 {do something}

so on the first line, set a variable BestYet to the value in the column you are searching.

On subsequent lines, simply test if the value in the column you are checking is

a) less than your target AND 
b) greater than `BestYet`

if it is, update BestYet. At the end, print BestYet.

In bash, apply the same logic, but read each line into a bash array and use ${a[n]} to get the n'th element.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!