bash, find nearest next value, forward and backward

前端 未结 4 1027
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-16 08:51

I have a data.txt file

1    2     3    4      5       6        7   
cat data.txt
13 245 1323 10.1111 10.2222 60.1111 60.22222
13 133 2325 11.2222 11.333  61.         


        
相关标签:
4条回答
  • 2021-01-16 09:15

    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.

    0 讨论(0)
  • 2021-01-16 09:21

    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.

    0 讨论(0)
  • 2021-01-16 09:34

    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
    
    0 讨论(0)
  • 2021-01-16 09:38

    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
    
    0 讨论(0)
提交回复
热议问题