从kml文件中删除多个条目的最佳方法

时间:2017-07-08 09:50:02

标签: bash macos command-line kml

我有一个非常大的KML文件(超过20000个标记)。它们以数字命名,数字从5开始增加到大约7000到27000。

<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个小时的工作时间单独删除它们。

3 个答案:

答案 0 :(得分:0)

在awk中有类似的东西:

$ awk '
/<Placemark>/ { d=""; b="" }         # d is delete, b is buffer, reset both
{ b=b $0 (/<\/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>
...

这是一个丑陋的黑客。有人可能会为你提供更好的东西,但如果它符合你的需要就试试。

答案 1 :(得分:0)

awk '$0 == "<Placemark>" {cnt=cnt+1} {arry[cnt]=arry[cnt]$0"\n";if ($0 ~ /<name>/) {match($0,/[[:digit:]]+/);num=substr($0,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。在我们这样做时,我们还检查文件中的名称索引。当我们找到这个时,我们模式匹配(匹配函数)中的数字,然后使用它来设置另一个数组麻木,跟踪每个放置元素的计数器的数字。我们最后循环遍历麻木中的每个元素,检查数字以确保它以50或00结束。如果是,则打印arry索引。

答案 2 :(得分:0)

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$

费斯特测试可以是:

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  

最好使用perl 5.22或更高版本