我的输入是一个制表符分隔的文本文件,其纬度和长度以 D-M-S 格式表示。 我要求输出以十进制为单位 我有 php 代码,但是计算速度非常慢。 使用 awk 可以更快地完成此操作吗?
node name id latitude longitude seq
nodex name1 70 N53-24-31.126 W6-20-46.982 59126
nodex name2 173 N53-20-28.885 W6-14-52.400 16190X
nodex name3 173 N53-20-28.885 W6-14-52.400 16191T
我的 PHP 代码与公式:
if ($dirLat == 'N') {$signLat = '+';} Else {$signLat = '-';}
if ($dirLat == 'E') {$signLon = '+';} Else {$signLon = '-';}
$latitudeDecimalDeg = $signLat . ($degLat + ($minLat/60) + ($secLat/3600));
$longitudeDecimalDeg = $signLon . ($degLon + ($minLon/60) + ($secLon/3600));
我非常确定 awk 会更快。这可以使用 awk 轻松完成,用
substr
和 split
分割每个字段。我把它变成了一个函数,以便于重用:
function dms2deg(s) {
dir = (substr(s, 1, 1) ~ /^[NE]/) ? 1 : -1
dms = substr(s, 2)
split(dms, arr, "-")
return dir * (arr[1] + arr[2]/60 + arr[3]/3600)
}
如果您已将上述内容放入 dms2deg 并且数据位于 infile 中,您将像这样使用 awk:
awk -f dms2deg -e 'NR>1 { print dms2deg($4), dms2deg($5) }' infile
输出:
53.4086 -6.34638
53.3414 -6.24789
53.3414 -6.24789
或者如果您想替换现有字段:
awk -f dms2deg -e 'NR>1 { $4 = dms2deg($4); $5 = dms2deg($5) } $1=$1' infile
输出:
node name id latitude longitude seq
nodex name1 70 53.4086 -6.34638 59126
nodex name2 173 53.3414 -6.24789 16190X
nodex name3 173 53.3414 -6.24789 16191T
column
会解决这个问题:
awk -f dms2deg -e 'NR>1 { $4 = dms2deg($4); $5 = dms2deg($5) } $1=$1' infile | column -t
输出:
node name id latitude longitude seq
nodex name1 70 53.4086 -6.34638 59126
nodex name2 173 53.3414 -6.24789 16190X
nodex name3 173 53.3414 -6.24789 16191T
我真的不知道它是否会更快,但恕我直言,这是在 awk 中执行此操作并保留间距的最快方法:
$ cat tst.awk
BEGIN{ FS="[- ]+" }
NR>1 {
sub( $7"-"$8"-"$9, ($7~/^E/?"+":"-") (substr($7,2) + $8/60 + $9/3600) )
sub( $4"-"$5"-"$6, ($4~/^N/?"+":"-") (substr($4,2) + $5/60 + $6/3600) )
}
1
$ cat file
node name id latitude longitude seq
nodex name1 70 N53-24-31.126 W6-20-46.982 59126
nodex name2 173 N53-20-28.885 W6-14-52.400 16190X
nodex name3 173 N53-20-28.885 W6-14-52.400 16191T
$ awk -f tst.awk file
node name id latitude longitude seq
nodex name1 70 +53.4086 -6.34638 59126
nodex name2 173 +53.3414 -6.24789 16190X
nodex name3 173 +53.3414 -6.24789 16191T
我有兴趣知道它是否比你的 PHP 脚本更快,所以如果你有机会比较它们,请发布结果。
如果你不关心保留间距,你可以使用:
BEGIN{ FS="[- ]+" }
NR == 1 { print; next }
{ print $1, $2, $3, ($4~/^N/?"+":"-") (substr($4,2) + $5/60 + $6/3600), ($7~/^E/?"+":"-") (substr($7,2) + $8/60 + $9/3600), $10 }
awk -F"[- ]+" 'NR==1 {print;next} {s1=($4~/N/)?1:-1;s2=($7~/E/)?1:-1;print $1,$2,$3,s1*(substr($4,2)+$5/60+$6/3600),s2*(substr($7,2)+$8/60+$9/3600),$10}' file
node name id latitude longitude seq
nodex name1 70 53.4086 -6.34638 59126
nodex name2 173 53.3414 -6.24789 16190X
nodex name3 173 53.3414 -6.24789 16191T
关于纬度和经度的快速说明 - 而不是针对固定常数对每行进行 4 次划分,
可以通过注意值的积分分量
dd
不会改变(除了将方向修改为 +/-
符号之外)来简化它,
所以不用除法,只需在
.
之后附加一个小数点 dd
,然后用零填充 ...
floor( ( 60 * mm + ss ) * 277777777777 )
# or 277777777777.777777777777777777……
...输出到 15 位数字到
+53.408646111109966
+53.341356944443488