Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash,向前和向后查找最近的下一个值_Bash_Awk_Find_Asort - Fatal编程技术网

bash,向前和向后查找最近的下一个值

bash,向前和向后查找最近的下一个值,bash,awk,find,asort,Bash,Awk,Find,Asort,我有一个data.txt文件 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.2222 61.3333 13 245 1323 12.3333 12.4444 62.3333 62.44444444 13 245 1323 13.4444 13.5555 63.4444 63.5

我有一个data.txt文件

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.2222 61.3333
13 245 1323 12.3333 12.4444 62.3333 62.44444444
13 245 1323 13.4444 13.5555 63.4444 63.5555
查找下一个最近的值:我的目标值是
11.6667
,它应该在
第4列中查找下一个最近的值,如
12.3333

查找最接近的上一个值:我的目标值是
62.9997
,它应该在
第6列中查找最接近的上一个值
62.3333

我可以通过以下方式找到下一个最近的(案例1)

awk-vc=4-vt=11.6667'{a[NR]=$c}END{
asort(a);d=a[NR]-t;d=d=1;i--){

m=a[i]-t;m=m您的解决方案看起来非常复杂(存储整个数组并对其进行排序),如果您重新考虑您的
awk
,我想您会看到
bash
解决方案

awk
中,您可以使用

FNR==1 {do something}
因此,在第一行,将变量
BestYet
设置为您正在搜索的列中的值

在随后的行中,只需测试正在检查的列中的值是否为

a) less than your target AND 
b) greater than `BestYet`
如果是,则更新
BestYet
。最后,打印
BestYet


bash
中,应用相同的逻辑,但将每一行读入一个bash数组,并使用
${a[n]}
获取第n个元素。

我不知道这是否是您正在寻找的,但这是我想到的,不知道
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
!/bin/sh
IFSBAK=$IFS
IFS=$'\n'
最好的=
对于“cat$1”中的行,请执行以下操作
IFS=$'\t'
arr=($line)
num=${arr[5]}
[[-z$best]]&&best=$num
如果第一部分为[$(bc):

awk -v v1="11.6667" '$4>v1 {print $4;exit}' file
12.3333
第二部分:

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

一气呵成:

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
试试这个:

$ 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)
}

bash是一个UNIX shell。shell是一个调用工具的环境,使用一种语言对这些调用进行排序。解析文本文件的UNIX工具是awk。您已经有了正确的方法,在bash中重新编写awk脚本将是完全错误的方法。感谢Ed Morton。这项工作很好。感谢上面的提示。
$ 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