从 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 结尾的地标
首先是解决方案;匹配除以 0050

结尾的任何内容
^(?:[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$  

仅匹配以 0050.
结尾的内容 所以你可以使用它在你想要的和你不想要的之间切换。

打印所有不以 0050

结尾的模式
perl -lne '$/=undef;print $& while/<Placemark>\s*?<name>(?:[7-9]\d|[1-2]\d\d)(?!00|50)\d\d.*?<\/Placemark>/sg' file

打印所有以 0050

结尾的模式
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或更高版本