假设我有一个包含 3 列和任意数量的行(行)的文件。每行对应 xyz 坐标。
1 2 3
4 5 6
7 8 9
10 11 12
...
如何计算第一和第二坐标、第二和第三坐标、第三和第四坐标等之间的距离?
这就是我所做的。但我认为还可以更简单:
a=`wc -l < oldfile`
for i in $(seq 2 $a); do
j=$((i-1))
sed -n "${j},${i} p" <oldfile
done > ala
split ala -l 2 ala.
for i in ala.??; do
echo `cat $i`| awk '{printf "%.10f \n", sqrt (($4-$1)^2 + ($5-$2)^2) + ($6-$3)^2}'
done > newfile
我欢迎任何答案。由于我对 Linux 编程非常陌生,所以使用 、 和/或 的简单命令split
将cat
受到echo
高度awk
赞赏:)。
谢谢。
答案1
以下awk
命令将从名为 的某个文件的行中读取空格分隔的 (x,y,z) 坐标file
,并计算每行之间的距离。
awk '
NR > 1 { printf "%f\n", sqrt(($1-x)^2 + ($2-y)^2 + ($3-z)^2) }
{ x=$1; y=$2; z=$3 }' file
上面的命令awk
将为除第一行之外的每一行写入从当前行给出的点到上一行给出的点的距离。变量x
、y
和z
将包含前一行的坐标,在计算和输出距离值后更新。
随着输入
7 4 3
17 6 2
-2 0 0
...这会产生
10.246951
20.024984
答案2
使用乐(以前称为 Perl_6)
简化问题以获取前六个值(每行 3 个):
raku -e 'my @a = words; for @a -> $x1,$y1,$z1,$x2,$y2,$z2 { \
say sqrt( ($x1 - $x2)**2 + ($y1 - $y2)**2 + ($z1 - $z2)**2) };'
#OR
raku -e 'my @a = words; for @a -> \x1,\y1,\z1,\x2,\y2,\z2 { \
say sqrt( (x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2 ) };'
Raku 允许无符号变量(第二个示例),一些程序员发现它更具可读性。文件被读入@a
数组,以空格分隔words
。声明了六个变量(第二个示例):x1,y1,z1
和x2,y2,z2
。距离方程按照 OP 的要求执行,并返回值。
[请注意,无符号变量是用前导反斜杠声明的,但从那时起可以在不使用反斜杠的情况下编写。需要注意的是,无印记变量通常是不可变的(对于声明常量很有用),请参阅下面的 URL 了解详细信息]。
输入示例(简化版):
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
16 17 18
示例输出(简化版):
5.196152422706632
5.196152422706632
5.196152422706632
对于最终版本,您需要做的就是指示 Raku 在将数据读入数组时创建重叠,@a
如下所示my @a=lines.rotor(2 => -1).words;
:使用@Kusalananda 慷慨提供的示例数据:
~$ cat file
7 4 3
17 6 2
-2 0 0
~$ raku -e 'my @a=lines.rotor(2 => -1).words; for @a -> \x1,\y1,\z1,\x2,\y2,\z2 {say sqrt((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)};' file
10.246950765959598
20.024984394500787
https://docs.raku.org/language/variables#index-entry-\_(sigilless_variables)
https://docs.raku.org/routine/rotor
https://raku.org
答案3
“取出”到底是什么意思:是“单独取出”还是“删除”?通常我会想到后者,但你的PS似乎表明前者?
假设是前者,您可以在 shell 中执行此操作:
# index of first row to print
n=3
tail -n +${n} <filename> | head -n 2
对于给定的 n=3,这将打印第三行和第四行。
答案4
不知道你的意思,我用这个解决方案来计算每行的 6D 距离。
awk 文件 dist.awk
function memorize()
{ for(i=1;i<=6;i++) previous[i]=$i ;}
NR>1 {
s=0 ;
for(i=1;i<=6;i++) s+=($i-previous[i])**2 ;
printf "dist=%f\n",sqrt(s) ;
}
{
memorize() ;
print ;
}
1
许多人更喜欢使用print
奇怪的是,根据你的数据,我得到了以下结果。
awk -f dist.awk original.data
1 2 3 4 5 6
dist=14.696938
7 8 9 10 11 12
dist=14.696938
13 14 15 16 17 18
dist=14.696938
19 20 21 22 23 24
(点在 6 维空间中对齐,距离以 sqrt(36*6) 为单位)
重点是 awk,可以记住前一行,并对它们进行计算。