bash,向前和向后查找最近的下一个值
我有一个data.txt文件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
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