使用awk将坐标d-m-s转换为十进制度数

使用awk将坐标d-m-s转换为十进制度数,awk,gawk,Awk,Gawk,我的输入是一个选项卡分隔的文本文件,在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 n

我的输入是一个选项卡分隔的文本文件,在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会更快。使用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中,并且数据在infle中,那么您将使用如下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
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
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 -f dms2deg -e 'NR>1 { $4 = dms2deg($4); $5 = dms2deg($5) } $1=$1' infile
输出:

53.4086 -6.34638
53.3414 -6.24789
53.3414 -6.24789
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
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 -f dms2deg -e 'NR>1 { $4 = dms2deg($4); $5 = dms2deg($5) } $1=$1' infile | column -t
输出:

53.4086 -6.34638
53.3414 -6.24789
53.3414 -6.24789
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
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会更快。使用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中,并且数据在infle中,那么您将使用如下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
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
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 -f dms2deg -e 'NR>1 { $4 = dms2deg($4); $5 = dms2deg($5) } $1=$1' infile
输出:

53.4086 -6.34638
53.3414 -6.24789
53.3414 -6.24789
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
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 -f dms2deg -e 'NR>1 { $4 = dms2deg($4); $5 = dms2deg($5) } $1=$1' infile | column -t
输出:

53.4086 -6.34638
53.3414 -6.24789
53.3414 -6.24789
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
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中实现并保持间距的最快方法:

$ 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中的var名称不使用前导的
$
符号,字符串连接也不需要
。只要
longDecDeg=signLon(degLon+(minLon/60)+(secLon/3600))
就会非常接近。然后是一个
printf(“%4.2fn\n”,longDecDeg)
。祝你好运。这是我的php代码:)很难相信这些代码会导致性能问题。可能是脚本中的其他内容,例如,您在哪里分配上面使用的变量?@EdMorton该表相当大,有超过10k条记录。使用php按记录更新它可能是其在awk中的slowvar名称不使用前导符号
$
的原因,而字符串串联不需要
。只要
longDecDeg=signLon(degLon+(minLon/60)+(secLon/3600))
就会非常接近。然后是一个
printf(“%4.2fn\n”,longDecDeg)
。祝你好运。这是我的php代码:)很难相信这些代码会导致性能问题。可能是脚本中的其他内容,例如,您在哪里分配上面使用的变量?@EdMorton该表相当大,有超过10k条记录。使用php更新每条记录可能是其slowI无法看到相同结果的原因。我的命令gawk-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}”new.txt node name id纬度经度seq nodex name 1 70-19.9383 0 nodex name 2 173-7.94275 0 nodex name 3 173-7.94303 0您在awk行中已从单引号
'
更改为双引号
”。我正在使用awk for windows,如果没有更改,它将无法工作:(我用没有单引号的代码创建了一个新文件dmsl.awk,然后我看到语法错误。gawk-F“[-]+”dms.awk file.txt我没有看到相同的结果。我的命令gawk-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)$3608++$10++)“new.txt节点名称id纬度经度seq nodex name1 70-19.9383 0 nodex name2 173-7.94275 0 nodex name3 173-7.94303 0您在awk行中已从单引号
更改为双引号
”。我正在使用awk for windows,如果没有更改,它将无法工作:(我用不带单引号的代码创建了一个新文件dmsl.awk,然后我看到了语法错误。gawk-F“[-]+”dms.awk file.txt由于OP显然在寻找最快的方法来实现它,所以可以使用
dir=(substr(s,1,1)~/^[NE]/-1:-1
而不是
dir=(substr(s,1,1)=“N”来保存substr()函数调用。)“| | substr(s,1,1)=“E”)?1:-1
。谢谢。效果很好。如何在awk-f dms2deg-E'NR>1{$4=dms2deg($4);$5=dms2deg($5)}上指定输出文件$1=$1'填充|列-t@SantoshPillai:将其重定向到具有
的文件,例如:
awk-f dms2deg'…'infle | column-t>outfile
。由于OP显然在寻找最快的方法来执行此操作,因此可以使用
dir=(substr(s,1,1)~/^[NE]/?1:-1
而不是
dir=(substr(s,1,1)=“N”| substr(s,1,1)=“E”)?1:-1
。谢谢。效果很好。如何在awk-f dms2deg-E'NR>1{$4=dms2deg($4);$5=dms2deg($5}上指定输出文件$1=$1'填充|列-t@SantoshPillai:将其重定向到带有
的文件,例如:
awk-f dms2deg'…'infle | column-t>outfile
。此解决方案也可以工作。但是,当我输出到文件时,结果显示在一行中。该文件在几秒钟内以awk处理,我的php代码花费了几分钟以上的时间没有理由让该脚本的输出全部显示在一行上,它使用您环境的默认行终止符一次打印一行。您前面提到,您在Windows中工作,可能存在一些Windows问题,idk。此解决方案也可以工作。但是,当我输出到文件时,结果是