用awk计算距离
我有如下所示的文本文件用awk计算距离,awk,Awk,我有如下所示的文本文件 CA 21.660 -6.795 11.323 C 28.811 -9.801 16.262 O 23.221 -9.266 13.799 CB 33.528 -11.934 17.900 N 21.660 -6.795 11.323 O 32.410 -8.539 16.566 我想计算原子坐标之间的距离。例如,我想读取文件夹中的所有文件并计算第一个和第二个原子、第一个和第三个
CA 21.660 -6.795 11.323
C 28.811 -9.801 16.262
O 23.221 -9.266 13.799
CB 33.528 -11.934 17.900
N 21.660 -6.795 11.323
O 32.410 -8.539 16.566
我想计算原子坐标之间的距离。例如,我想读取文件夹中的所有文件并计算第一个和第二个原子、第一个和第三个原子、第一个和第四个原子等之间的距离。然后,第二个和第三个原子、第二个和第四个原子、第二个和第五个原子等。公式是SQRT((X1-X2)^2+(Y1-Y2)^2+(Z1-Z2)^2)。我想用输入文件的名称将每个文件的输出保存到另一个文件夹中。我怎样才能用awk做到这一点
期望输出
CA-C 4.52
CA-O 3.80
CA-CB 5.68
CA-N 8.94
--
--
--
N-O 5.98
谢谢你的帮助 这样的结果听起来像是你想要的,但显然两个结果都不符合你所说的,因此它们应该澄清你的算法:
$ awk 'NR>1{print p[1]"-"$1,sqrt((p[2]-$2)^2 + (p[3]-$3)^2 + (p[4]-$4)^2)} {split($0,p) }' file
CA-C 9.19601
C-O 6.13194
O-CB 11.4092
CB-N 14.5092
N-O 12.0869
$ awk 'NR>1{print p[1]"-"$1,sqrt(($2-p[2])^2 + ($3-p[3])^2 + ($4-p[4])^2)} {split($0,p) }' file
CA-C 9.19601
C-O 6.13194
O-CB 11.4092
CB-N 14.5092
N-O 12.0869
如果atoms是包含您的数据的文件
awk '{ p[NR,0]=$1;p[NR,1]=$2;p[NR,2]=$3;p[NR,3]=$4; for (j=1;j<=NR-1;j++) print p[j,0]"-"$1,sqrt((p[NR,1]-p[j,1])^2+(p[NR,2]-p[j,2])^2+(p[NR,3]-p[j,3])^2) }' atoms
CA-C 9.19601
CA-O 3.83055
C-O 6.13194
CA-CB 14.5092
C-CB 5.42981
O-CB 11.4092
CA-N 0
C-N 9.19601
O-N 3.83055
CB-N 14.5092
CA-O 12.0869
C-O 3.82595
O-O 9.62406
CB-O 3.81517
N-O 12.0869
awk'{p[NR,0]=$1;p[NR,1]=$2;p[NR,2]=$3;p[NR,3]=$4;对于(j=1;j这里有一种使用gnuawk
的方法:
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--}' file file
如果需要对当前工作目录中的多个文件执行此操作,并且假设此目录中只有感兴趣的文件,则可以围绕awk
语句包装for
循环。显然,您需要将/path/to/folder/
更改为您选择的路径,以使其正常工作:
for i in *; do 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 > /path/to/folder/" FILENAME } NR--}' "$i"{,}; done
for i in*;do awk'FNR==NR{a[NR]=0;next}{for(i=FNR+1;i以下是awk中的代码:
awk '{a[NR]=$0}
END
{
for(i=1;i<=NR;i++)
{split(a[i],k);
for(j=i+1;j<=NR;j++)
{
split(a[j],l);
dist=(k[2]-l[2])*(k[2]-l[2])+(k[3]-l[3])*(k[3]-l[3])+(k[4]-l[4])*(k[4]-l[4]);
print k[1]"-"l[1],sqrt(dist);
}
}
}' your_file
执行:
> awk '{a[NR]=$0}END{for(i=1;i<=NR;i++){split(a[i],k);for(j=i+1;j<=NR;j++){split(a[j],l);dist=(k[2]-l[2])*(k[2]-l[2])+(k[3]-l[3])*(k[3]-l[3])+(k[4]-l[4])*(k[4]-l[4]);print k[1]"-"l[1],sqrt(dist);}}}' temp
CA-C 9.19601
CA-O 3.83055
CA-CB 14.5092
CA-N 0
CA-O 12.0869
C-O 6.13194
C-CB 5.42981
C-N 9.19601
C-O 3.82595
O-CB 11.4092
O-N 3.83055
O-O 9.62406
CB-N 14.5092
CB-O 3.81517
N-O 12.0869
>
>awk'{a[NR]=$0}END{for(i=1;iPerl解决方案可以是:
#!/usr/bin/perl
use strict;
use warnings;
my @data = map [split], <DATA>;
for (my $i = 0; $i < @data; $i++) {
for (my $j = $i+1; $j < @data; $j++) {
my $d = distance( @data[$i, $j]);
printf("%-6s%7.4f\n",
join("-", map $_->[0], @data[$i, $j]), $d) if $d <= 6;
}
}
sub distance {
my ($coord1, $coord2) = @_;
my $sum;
for my $k (1 .. $#$coord1) {
$sum += ($coord1->[$k] - $coord2->[$k])**2;
}
return sqrt $sum;
}
__DATA__
CA 21.660 -6.795 11.323
C 28.811 -9.801 16.262
O 23.221 -9.266 13.799
CB 33.528 -11.934 17.900
N 21.660 -6.795 11.323
O 32.410 -8.539 16.566
!/usr/bin/perl
严格使用;
使用警告;
my@data=map[split];
对于(我的$i=0;$i<@data;$i++){
对于(my$j=$i+1;$j<@data;$j++){
my$d=距离(@data[$i,$j]);
printf(“%-6s%7.4f\n”,
如果$d[$k]-$coord2->[$k])**2,则加入(“-”,map$\->[0],@data[$i,$j]),$d);
}
返回sqrt$sum;
}
__资料__
CA 21.660-6.795 11.323
C 28.811-9.80116.262
O 23.221-9.266 13.799
CB 33.528-11.934 17.900
N 21.660-6.795 11.323
O 32.410-8.539 16.566
可以从学习awk开始。或者您希望我们提供解决方案吗?如果您有与编程相关的特定问题,请说出它的名称。
> awk '{a[NR]=$0}END{for(i=1;i<=NR;i++){split(a[i],k);for(j=i+1;j<=NR;j++){split(a[j],l);dist=(k[2]-l[2])*(k[2]-l[2])+(k[3]-l[3])*(k[3]-l[3])+(k[4]-l[4])*(k[4]-l[4]);print k[1]"-"l[1],sqrt(dist);}}}' temp
CA-C 9.19601
CA-O 3.83055
CA-CB 14.5092
CA-N 0
CA-O 12.0869
C-O 6.13194
C-CB 5.42981
C-N 9.19601
C-O 3.82595
O-CB 11.4092
O-N 3.83055
O-O 9.62406
CB-N 14.5092
CB-O 3.81517
N-O 12.0869
>
#!/usr/bin/perl
use strict;
use warnings;
my @data = map [split], <DATA>;
for (my $i = 0; $i < @data; $i++) {
for (my $j = $i+1; $j < @data; $j++) {
my $d = distance( @data[$i, $j]);
printf("%-6s%7.4f\n",
join("-", map $_->[0], @data[$i, $j]), $d) if $d <= 6;
}
}
sub distance {
my ($coord1, $coord2) = @_;
my $sum;
for my $k (1 .. $#$coord1) {
$sum += ($coord1->[$k] - $coord2->[$k])**2;
}
return sqrt $sum;
}
__DATA__
CA 21.660 -6.795 11.323
C 28.811 -9.801 16.262
O 23.221 -9.266 13.799
CB 33.528 -11.934 17.900
N 21.660 -6.795 11.323
O 32.410 -8.539 16.566