从 kml 文件中删除多个条目的最佳方法
Best way to remove multiple entries from kml file
我有一个非常大的 KML 文件(超过 20000 个地标)。它们由从大约 7000 到 27000 之间以 5 递增的数字命名。
<Placemark>
<name>7750</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
我想删除所有不是以 00 或 50 结尾的地标。每 5 米有一个地标会降低网站上一些低端设备的速度。
是否有一些脚本、命令或任何东西可以检查名称,如果它不是以 00 或 50 结尾,则删除该条目的 <Placemark>
到 </Placemark>
?
你真的可以节省我 10 个小时的工作时间来单独删除它们。
awk 中的类似内容:
$ awk '
/<Placemark>/ { d=""; b="" } # d is delete, b is buffer, reset both
{ b=b [=10=] (/<\/Placemark>/?"":ORS) } # gather data to d
!/[50]0</ && /<\/name>/ { d=1 } # if not 50 or 00 set del flag
/<\/Placemark>/ && d!=1 { print b } # print b if not marked delete
' file
它只适用于格式正确的输入,尤其是:
...
</Placemark>
<Placemark>
...
<name>1234</name>
...
不是:
...
</Placemark><Placemark>
... <!-- or: -->
<name>1234
</name>
...
这是一个丑陋的 hack。有人可能会为您设置更好的东西,但如果适合您的需要,请尝试一下。
awk '[=10=] == "<Placemark>" {cnt=cnt+1} {arry[cnt]=arry[cnt][=10=]"\n";if ([=10=] ~ /<name>/) {match([=10=],/[[:digit:]]+/);num=substr([=10=],RSTART,RLENGTH);numbs[num]=cnt}} END { for ( i in numbs ) {if ( substr(i,length(i)-1,length(i)) == "00" || substr(i,length(i)-1,length(i)) == "50") { print arry[numbs[i]] } } }' filename
另一种 awk 解决方案如上。当 $0 = 时,我们首先为数组设置一个计数器。然后我们为文件中的每个 Placement 元素设置数组 arry。当我们这样做时,我们还会检查文件中的名称索引。当我们找到它时,我们将模式匹配(匹配函数)中的数字,然后使用它来设置另一个数组 numbs,该数组根据每个放置元素的计数器跟踪数字。我们最终遍历 numbs 中的每个元素,检查数字以确保它以 50 或 00 结尾。如果是,则打印 arry 索引。
一个Perl-one liner解决方案!
我想删除所有不以 00 或 50 结尾的地标
首先是解决方案;匹配除以 00
或 50
结尾的任何内容
^(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d$
演示:
^(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d$
fest 测试可以是:
perl -le 'print for grep{ /^(?:[7-9]\d|[1-2]\d\d)(?=00|50)\d\d$/ } 7000..27000'
然后读取整个文件一次:
$/=undef;
然后用 while 循环读取所有匹配项:
while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg
s
标志用于单行读取或.
可以匹配换行,g
用于全局搜索
然后打印匹配 (S&
):
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file
匹配模式:
<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>
演示:
<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>
注意:
如果你注意到这部分 (?!00|50)
它是一个排除匹配器,通过使用 lookahead,你可以使它相反,这意味着:
^(?:[7-9]\d|[1-2]\d\d)(?=00|50)\d\d$
仅匹配以 00
或 50
.
结尾的内容
所以你可以使用它在你想要的和你不想要的之间切换。
打印所有不以 00
或 50
结尾的模式
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file
打印所有以 00
或 50
结尾的模式
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file
如何替代
如果你喜欢,你可以使用运算符:s/regex-match/substitute-string/
perl -pe '$/=undef;s/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/==>DELETE<==/sg' file
测试:
输入:
before...
<Placemark>
<name>7700</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
---------
before...
<Placemark>
<name>7701</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
--------
before...
<Placemark>
<name>27650</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
--------
before...
<Placemark>
<name>27651</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
end.
输出:
before...
<Placemark>
<name>7700</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
---------
before...
==>DELETE<==
after...
--------
before...
<Placemark>
<name>27650</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
--------
before...
==>DELETE<==
after...
end.
注 2:
您可以使用 -i
进行就地编辑
perl -i.bak -pe ' ... the rest of the script ...' file
最好使用perl5.22
或更高版本
我有一个非常大的 KML 文件(超过 20000 个地标)。它们由从大约 7000 到 27000 之间以 5 递增的数字命名。
<Placemark>
<name>7750</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
我想删除所有不是以 00 或 50 结尾的地标。每 5 米有一个地标会降低网站上一些低端设备的速度。
是否有一些脚本、命令或任何东西可以检查名称,如果它不是以 00 或 50 结尾,则删除该条目的 <Placemark>
到 </Placemark>
?
你真的可以节省我 10 个小时的工作时间来单独删除它们。
awk 中的类似内容:
$ awk '
/<Placemark>/ { d=""; b="" } # d is delete, b is buffer, reset both
{ b=b [=10=] (/<\/Placemark>/?"":ORS) } # gather data to d
!/[50]0</ && /<\/name>/ { d=1 } # if not 50 or 00 set del flag
/<\/Placemark>/ && d!=1 { print b } # print b if not marked delete
' file
它只适用于格式正确的输入,尤其是:
...
</Placemark>
<Placemark>
...
<name>1234</name>
...
不是:
...
</Placemark><Placemark>
... <!-- or: -->
<name>1234
</name>
...
这是一个丑陋的 hack。有人可能会为您设置更好的东西,但如果适合您的需要,请尝试一下。
awk '[=10=] == "<Placemark>" {cnt=cnt+1} {arry[cnt]=arry[cnt][=10=]"\n";if ([=10=] ~ /<name>/) {match([=10=],/[[:digit:]]+/);num=substr([=10=],RSTART,RLENGTH);numbs[num]=cnt}} END { for ( i in numbs ) {if ( substr(i,length(i)-1,length(i)) == "00" || substr(i,length(i)-1,length(i)) == "50") { print arry[numbs[i]] } } }' filename
另一种 awk 解决方案如上。当 $0 = 时,我们首先为数组设置一个计数器。然后我们为文件中的每个 Placement 元素设置数组 arry。当我们这样做时,我们还会检查文件中的名称索引。当我们找到它时,我们将模式匹配(匹配函数)中的数字,然后使用它来设置另一个数组 numbs,该数组根据每个放置元素的计数器跟踪数字。我们最终遍历 numbs 中的每个元素,检查数字以确保它以 50 或 00 结尾。如果是,则打印 arry 索引。
一个Perl-one liner解决方案!
我想删除所有不以 00 或 50 结尾的地标
首先是解决方案;匹配除以 00
或 50
^(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d$
演示:
^(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d$
fest 测试可以是:
perl -le 'print for grep{ /^(?:[7-9]\d|[1-2]\d\d)(?=00|50)\d\d$/ } 7000..27000'
然后读取整个文件一次:
$/=undef;
然后用 while 循环读取所有匹配项:
while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg
s
标志用于单行读取或.
可以匹配换行,g
用于全局搜索
然后打印匹配 (S&
):
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file
匹配模式:
<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>
演示:
<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>
注意:
如果你注意到这部分 (?!00|50)
它是一个排除匹配器,通过使用 lookahead,你可以使它相反,这意味着:
^(?:[7-9]\d|[1-2]\d\d)(?=00|50)\d\d$
仅匹配以 00
或 50
.
结尾的内容
所以你可以使用它在你想要的和你不想要的之间切换。
打印所有不以 00
或 50
结尾的模式
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file
打印所有以 00
或 50
结尾的模式
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file
如何替代
如果你喜欢,你可以使用运算符:s/regex-match/substitute-string/
perl -pe '$/=undef;s/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/==>DELETE<==/sg' file
测试:
输入:
before...
<Placemark>
<name>7700</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
---------
before...
<Placemark>
<name>7701</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
--------
before...
<Placemark>
<name>27650</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
--------
before...
<Placemark>
<name>27651</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
end.
输出:
before...
<Placemark>
<name>7700</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
---------
before...
==>DELETE<==
after...
--------
before...
<Placemark>
<name>27650</name>
<description><![CDATA[converted by:</br><a href="http://gridreferencefinder.com/">GridReferenceFinder.com</a></br>]]></description>
<Point>
<coordinates>-0.99153654,52.225002,0</coordinates>
</Point>
</Placemark>
after...
--------
before...
==>DELETE<==
after...
end.
注 2:
您可以使用 -i
进行就地编辑
perl -i.bak -pe ' ... the rest of the script ...' file
最好使用perl5.22
或更高版本