我需要帮助! 我有几个要点ABCDEF ...的位置是这样的:
A 0.00 0.50 0.10
B 1.00 2.50 2.00
C 0.70 0.88 1.29
D 2.13 2.90 0.11
E 1.99 0.77 0.69
...
我的目的是计算AB,BC,CD,EF等的距离,并将它们的总和与如下形式的输出相加:
sum_distance(AB)
sum_distance(AB+BC)
sum_distance(AB+BC+CD)
sum_distance(AB+BC+CD+DE)
sum_distance(AB+BC+CD+DE+EF)
....
我在awk网上发现可以做到这一点,并适用于我的案子。但是,没有结果或错误导出到屏幕上。你能帮我解决这种情况吗?
bash shell,awk
awk 'FNR==NR { a[NR]=$0; next } { for (i=FNR+1;i<=NR-1;i++) {split(a[i],b); print $1 "-" b[1], sqrt(($2-b[2])^2 + ($3-b[3])^2 + ($4-b[4])^2) | "column -t" } NR--}'
输出:
2.934280150
4.728297987
7.470140434
9.682130488
11.92469598
......
答案 0 :(得分:2)
对于此琐碎的任务,您不需要如此复杂的脚本。尝试以下方法:
awk 'NR>1{ printf "%.9f\n",s+=sqrt(($2-x)^2+($3-y)^2+($4-z)^2) }
{ x=$2;y=$3;z=$4 }' file
对于A
以外的所有点,计算距离,将其加到总和s
上并打印总和。对于所有点,将坐标保留在x, y, z
中以进行下一步计算。其输出与gawk相似:
2.934280150
4.728297987
7.470140434
9.682130488
答案 1 :(得分:1)
尝试一下:
awk 'function d(a,b){split(a,x);split(b,y);return sqrt((x[2]-y[2])^2 + (x[3]-y[3])^2 + (x[4]-y[4])^2);} {p[FNR]=$0} FNR>1{sum[FNR]=sum[FNR-1]+d(p[FNR-1],p[FNR]);printf "%.9f\n",sum[FNR];}' file
具有file
这样的内容:
A 0.00 0.50 0.10
B 1.00 2.50 2.00
C 0.70 0.88 1.29
D 2.13 2.90 0.11
E 1.99 0.77 0.69
将提供如下输出:
2.934280150
4.728297987
7.470140434
9.682130488
您没有提供点F
,因此您的最后一行输出实际上不能在此处计算。
在此处输入几行:
awk '
function d(a,b){
split(a,x);
split(b,y);
return sqrt((x[2]-y[2])^2 + (x[3]-y[3])^2 + (x[4]-y[4])^2);
}
{p[FNR]=$0}
FNR>1{
sum[FNR]=sum[FNR-1]+d(p[FNR-1],p[FNR]);
printf "%.9f\n",sum[FNR];
}' file
这里非常简单,功能d
用于确定距离。并重用前一行的总和。
有趣的是,如果您要计算图形的总距离,请首先从一个点开始,然后逐渐将点添加到图形中。即:
sum_distance(AB)
sum_distance(AB+BC+AC)
sum_distance(AB+BC+AC+AD+BD+CD)
...
然后可以做一点改进,就像这样:
$ awk 'function d(a,b){split(a,x);split(b,y);return sqrt((x[2]-y[2])^2 + (x[3]-y[3])^2 + (x[4]-y[4])^2);} {p[FNR]=$0} FNR>1{sum[FNR]=sum[FNR-1];for(i=FNR-1;i>0;i--)sum[FNR]+=d(p[i],p[FNR]);printf "%.9f\n",sum[FNR];}' file
2.934280150
6.160254691
14.349070561
22.466306583
答案 2 :(得分:1)
什么是基本规则? (切勿在您不懂的互联网上使用代码...)
您尝试使用的awk
脚本问题不完全是您的情况。通过设置FNR==NR
,然后使用循环限制(i=FNR+1;i<=NR-1;i++)
,可以期待多个输入文件。对于您的情况,实际上可以通过完全删除循环来简化脚本,因为您只有一个输入文件。
您只需要保存第一行,然后使用next
读取下一行,计算并输出前一行与当前行之间的距离,将当前行设置为a[]
中的行数组并重复直到行用完,例如
awk '{
a[NR]=$0
if (NR == 1)
next
split(a[NR-1],b)
printf "%s\t%s\n", b[1] "-" $1,
sqrt(($2-b[2])^2 + ($3-b[3])^2 + ($4-b[4])^2)
a[NR]=$0
}'
示例输入文件
$ cat f
A 0.00 0.50 0.10
B 1.00 2.50 2.00
C 0.70 0.88 1.29
D 2.13 2.90 0.11
E 1.99 0.77 0.69
使用/输出示例
只需将脚本粘贴到终端中,然后在文件名末尾添加文件名,例如
$ awk '{
> a[NR]=$0
> if (NR == 1)
> next
> split(a[NR-1],b)
> printf "%s\t%s\n", b[1] "-" $1,
> sqrt(($2-b[2])^2 + ($3-b[3])^2 + ($4-b[4])^2)
> a[NR]=$0
> }' f
A-B 2.93428
B-C 1.79402
C-D 2.74184
D-E 2.21199
仔细检查一下,如果还有其他问题,请告诉我。