用jq简化geojson坐标精度
Simplify geojson coordinates precision with jq
我正在使用 jq
来更改一些属性并减轻 geojson
文件的重量。坐标有太多小数,所以我想简化为6位小数。
文件原来是这样的:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Point",
"coordinates": [
-69.23583984375,
45.460130637921004
]
}
},
...
]
}
我想要那个精度:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Point",
"coordinates": [
-69.235840,
45.460131
]
}
},
...
]
}
有什么建议吗?
GNU Awk 可能是一种可能性:
awk '/coordinates/ { lne=NR } (NR==lne+1 || NR==lne+2) && /-?[[:digit:]]+\.[[:digit:]]++/ { match([=10=],/-?[[:digit:]]+\.[[:digit:]]++/);printf "%s%.6f%s\n",substr([=10=],1,RSTART-1),substr([=10=],RSTART,RLENGTH),substr([=10=],RSTART+RLENGTH+1);next }1' file
解释:
awk '/coordinates/ {
lne=NR # Track the line number when we see a "coordinates" tag
} (NR==lne+1 || NR==lne+2) && /-?[[:digit:]]+\.[[:digit:]]++/ {
match([=11=],/-?[[:digit:]]+\.[[:digit:]]++/); # When the line is one or two ahead of coordinates, and the line contains a floating point number, extract that floating point number.
printf "%s%.6f%s\n",substr([=11=],1,RSTART-1),substr([=11=],RSTART,RLENGTH),substr([=11=],RSTART+RLENGTH+1); # Construct the line with the data before the floating point number, the number to 6 decimal places and then the text after the number
next # Skip to the next line
}1' file # Use 1 to print both modified and unmodified lines.
您可以通过 Perl 脚本将您的 JSON 重写为像这样具有 6 位小数的数字的任何看起来像浮点数的东西 - 但它是有点笨拙,会编辑 JSON 中的 所有 看起来像浮点数的东西,但只有你知道这是否是个问题。
GenerateJSON | perl -pe 's/([+-]?[0-9]+[.]?[0-9]+)/sprintf("%.6f",$&)/ge'
示例输出
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Point",
"coordinates": [
-69.235840,
45.460131
]
}
},
...
]
}
它基本上是一个替换,但是最后的 /ge
使 Perl evaluate
替换字符串中的 sprintf
。
请注意 Perl 是 macOS 的标准部分 - 即自动包含在所有版本中。
jq
支持的数学库中没有直接的类似于 sprintf
的函数,允许您以指定的精度格式化浮点数,例如说 '%2.5f'
。但是您可以使用字符串函数将数字转换为浮点数并提取数字并将其转换回来
jq '.features[].geometry.coordinates |=
map( tostring | capture("(?<n>-?[0-9]+\.[0-9]{6})").n | tonumber )'
请注意,当浮点数以科学记数法表示时,不起作用,例如像 1.5e9
这样的格式
中的建议更好,它不涉及任何字符串操作。
我正在使用 jq
来更改一些属性并减轻 geojson
文件的重量。坐标有太多小数,所以我想简化为6位小数。
文件原来是这样的:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Point",
"coordinates": [
-69.23583984375,
45.460130637921004
]
}
},
...
]
}
我想要那个精度:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Point",
"coordinates": [
-69.235840,
45.460131
]
}
},
...
]
}
有什么建议吗?
GNU Awk 可能是一种可能性:
awk '/coordinates/ { lne=NR } (NR==lne+1 || NR==lne+2) && /-?[[:digit:]]+\.[[:digit:]]++/ { match([=10=],/-?[[:digit:]]+\.[[:digit:]]++/);printf "%s%.6f%s\n",substr([=10=],1,RSTART-1),substr([=10=],RSTART,RLENGTH),substr([=10=],RSTART+RLENGTH+1);next }1' file
解释:
awk '/coordinates/ {
lne=NR # Track the line number when we see a "coordinates" tag
} (NR==lne+1 || NR==lne+2) && /-?[[:digit:]]+\.[[:digit:]]++/ {
match([=11=],/-?[[:digit:]]+\.[[:digit:]]++/); # When the line is one or two ahead of coordinates, and the line contains a floating point number, extract that floating point number.
printf "%s%.6f%s\n",substr([=11=],1,RSTART-1),substr([=11=],RSTART,RLENGTH),substr([=11=],RSTART+RLENGTH+1); # Construct the line with the data before the floating point number, the number to 6 decimal places and then the text after the number
next # Skip to the next line
}1' file # Use 1 to print both modified and unmodified lines.
您可以通过 Perl 脚本将您的 JSON 重写为像这样具有 6 位小数的数字的任何看起来像浮点数的东西 - 但它是有点笨拙,会编辑 JSON 中的 所有 看起来像浮点数的东西,但只有你知道这是否是个问题。
GenerateJSON | perl -pe 's/([+-]?[0-9]+[.]?[0-9]+)/sprintf("%.6f",$&)/ge'
示例输出
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Point",
"coordinates": [
-69.235840,
45.460131
]
}
},
...
]
}
它基本上是一个替换,但是最后的 /ge
使 Perl evaluate
替换字符串中的 sprintf
。
请注意 Perl 是 macOS 的标准部分 - 即自动包含在所有版本中。
jq
支持的数学库中没有直接的类似于 sprintf
的函数,允许您以指定的精度格式化浮点数,例如说 '%2.5f'
。但是您可以使用字符串函数将数字转换为浮点数并提取数字并将其转换回来
jq '.features[].geometry.coordinates |=
map( tostring | capture("(?<n>-?[0-9]+\.[0-9]{6})").n | tonumber )'
请注意,当浮点数以科学记数法表示时,不起作用,例如像 1.5e9