是否有一个Linux命令行工具从XML文件中删除部分(不知道这是否是正确的术语)?

我正在尝试对包含电视节目预告信息的XMLTV格式文件进行一些操作。 在文件内部分是这样的部分:

<programme start="20141215220000 -0500" stop="20141216060000 -0500" channel="someid.someaddress.com"> <title lang="en">Local Programming</title> <length units="hours">1</length> <episode-num system="common">S00E00</episode-num> <episode-num system="dd_progid">SH00019112.0000</episode-num> <previously-shown /> </programme> 

正如你所看到的第二行包含这个:

  <title lang="en">Local Programming</title> 

我想find的是一些在Linux中运行的命令行实用程序,它可以查找特定的行,如果存在,请删除程序标记之间的所有内容。 我不是很熟悉XML文件,所以我不知道这个数据块是否有一个特定的名字,但是只要标题是“本地编程”,我只想删除整个部分。

如果我只能在标题为“本地编程”的情况下删除该块,并且第一行中的通道值是某个特定值,那么它实际上对我的目的会更好,因为我只需要删除特定通道的这些值。在任何通道上删除所有“本地编程”块都不会造成任何损害,而寻找两个值可能会使这个问题变得更加困难。 它必须是一个命令行实用程序,因为它将从一个简短的shell脚本中调用。

基本上我只是想找出工作的最佳工具。 我不是一个程序员(除非你数了几行bash shell脚本,它只是顺序地运行几个东西,所以我想用一个现有的命令行工具,如果可能的话),但我也不利于拉新东西。 有什么build议么?

编辑:什么工作是Charles Duffybuild议的xmlstarlet工具,但只有当我没有尝试使用–var选项,而是直接指定值。 例如,这将从文件xmltv.xml中删除标题为“本地编程”的所有块:

 xmlstarlet ed --delete "//programme[title='Local Programming']" <xmltv.xml >newfile.xml 

如果我只想在标题为“本地编程”的情况下删除块,并且第一行的通道值是某个特定的值,那么看起来这是工作的:

 xmlstarlet ed --delete "//programme[title='Local Programming'][@channel='someid.someaddress.com']" <xmltv.xml >newfile.xml 

这正是我所期待的,所以我认为这个问题已经解决了。 谢谢所有回答的人。

删除任何具有英文标题“ Local Programming和频道someid.someaddress.com

 xmlstarlet ed \ --var chan "'someid.someaddress.com'" \ --var name "'Local Programming'" \ --delete '//programme[title[@lang="en"]=$name][@channel=$chan]' \ <in.xml >out.xml && mv out.xml in.xml 

如果你的目标是旧的XMLStarlet版本,你可能需要自己做替换 – 使用"Local Programming"代替$name"someid.someaddress.com"代替$chan – 但上面的内容是已知的对付1.5.0版本。

这需要工具XMLStarlet ,它应该可用于安装在分发供应商的存储库中。

请注意,您没有显示文档的名称空间声明 – 如果在父项中指定了xmlns='...' ,则可能需要进行一些调整。

除了正确的XML处理外,正如另一个答案中所举例说明的,人们总是可以采用传统的方式:将XML作为纯文本处理。 在Perl中:

 cat fancy.xml | perl -ne 'BEGIN{$/=undef;} print grep { /^<programme/ ? !m{<title\s+lang="en">Local\s+Programming</title>} : 1 } split qr{(<programme.*?</programme>)}s' 

这将读取整个输入XML(通过重置输入记录分隔符),将其切换到程序块的平面列表以及它们之间的所有内容( split() ),然后过滤出包含所查找字符串的程序块他们( grep() )。