【问题标题】:convert co-ordinate d-m-s to decimal degrees using awk使用 awk 将坐标 d-m-s 转换为十进制度
【发布时间】:2013-11-19 06:10:40
【问题描述】:

我的输入是一个制表符分隔的文本文件,在 D-M-S 中带有 lat long。 我要求输出为十进制度 我在 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 中的变量名称不使用前导 $ 符号,并且字符串连接不需要 .。只是longDecDeg = signLon (degLon + (minLon/60) + (secLon/3600)) 将非常接近。然后是printf("%4.2fn\n", longDecDeg)。祝你好运。
  • 这是我的 php 代码 :)
  • 很难相信那个代码会导致你的性能问题。也许您的脚本中有其他内容,例如您在哪里分配上面使用的变量?
  • @EdMorton 该表非常大,有超过 10k 条记录。使用 php 更新每条记录可能是它速度慢的原因

标签: awk gawk


【解决方案1】:

我很确定 awk 会更快。这很容易用 awk 完成,用substrsplit 分割每个字段。我把它变成了一个更容易重用的函数:

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

【讨论】:

  • 由于 OP 显然正在寻找最快的方法,您可以使用 dir = (substr(s, 1, 1) ~ /^[NE]/) ? 1 : -1 而不是 dir = (substr(s, 1, 1) == "N" || substr(s, 1, 1) == "E") ? 1 : -1 来保存 substr() 函数调用。
  • 谢谢。效果很好。如何在 awk -f dms2deg -e 'NR>1 { $4 = dms2deg($4); 上指定输出文件$5 = dms2deg($5) } $1=$1' infile |列-t
  • @SantoshPillai:将其重定向到带有> 的文件,例如:awk -f dms2deg '...' infile | column -t > outfile
【解决方案2】:

我真的不知道它是否会更快,但恕我直言,这是您可以在 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 中处理,我的 php 代码花费了几分钟以上
  • 没有理由将该脚本的输出全部显示在一行上,它使用您环境的默认行终止符一次打印每一行。您之前提到您在 Windows 中工作,也许有一些 Windows 问题,idk。
【解决方案3】:
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

【讨论】:

  • 我没有看到相同的结果。我的命令 gawk -F"[- ]+" "NR==1 {print;next} {s1=($4~/N/)?1:-1;s2=($7~/E/)?1:- 1;打印 $1,$2,$3,s1*(substr($4,2)+$5/60+$6/3600),s2*(substr($7,2)+$8/60+$9/3600),$10}" new.txt 节点名称 id 纬度经度 seq nodex name1 70 -19.9383 0 nodex name2 173 -7.94275 0 nodex name3 173 -7.94303 0
  • 你已经从 awk 行中的单引号 ' 更改为双引号 "
  • 我在 Windows 上使用 awk,如果不进行更改,它将无法工作:(
  • 我用不带单引号的代码创建了一个新文件 dmsl.awk,然后我看到语法错误。 gawk -F"[-]+" dms.awk 文件.txt
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 2013-01-11
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多