使用 sed 过滤 RSS 项目

使用 sed 过滤 RSS 项目

我想编写一个脚本:

  • 接受一些 RSS 源 URL 作为输入
  • 下载提要
  • 删除所有与某些正则表达式不匹配的标签<item> ...</item>title

以下示例可以说明这一点。假设我们有一个包含以下三个项目的 RSS Feed:

  • Project Foo——让我们开始吧!
  • 完全不同的东西
  • Project Foo 的另一个更新

我只想保留标题中带有“Project Foo”的项目。

输入文件示例:

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>My glorious newsfeed</title>
<description>...</description>
<link>...</link>
<language>...</language>
<pubDate>...</pubDate>

<item>
<title>Project Foo - Let's get started!</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

<item>
<title>Something else entirely</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

<item>
<title>Another update on Project Foo</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

</channel>
</rss>

输出文件示例:

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>My glorious newsfeed</title>
<description>...</description>
<link>...</link>
<language>...</language>
<pubDate>...</pubDate>

<item>
<title>Project Foo - Let's get started!</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

<item>
<title>Another update on Project Foo</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

</channel>
</rss>

如果可能的话,我想远离诸如此类的东西python,而使用命令行工具来做到这一点。但我是一个使用sed等的新手,需要一些帮助:)

以下是我目前所掌握的信息:

cat sample-feed.xml \
  | tr -d '\n' \
  | sed $'s/\<item\>/\\\n\<item\>/g;s/\<\/channel\><\/rss\>/\\\n\<\/channel\><\/rss\>/g' \
  | sed '/^\<item\>/ d'

首先,我删除所有换行符。然后,我添加换行符,使每<item>...</item>行都占一行。到目前为止,最后一个命令删除了所有以 开头的行<item>。对于

结果是有效的 RSS 提要,没有任何项目:

<?xml version="1.0" encoding="iso-8859-1"?><rss version="2.0"><channel><title>My glorious newsfeed</title><description>...</description><link>...</link><language>...</language><pubDate>...</pubDate>    
</channel></rss>

为了使这个工作使用 URL 而不是本地文件,我只需用cat sample-feed.xml替换curl -s <some url>

但是仍然缺少的是对命令的修改sed '/^\<item\>/ d',该修改仅删除以“Project Foo”开头<item>但不包含“Project Foo”的行。

所以,如果你能帮我弄清楚最后一行应该说什么,我会非常高兴。另一方面,我相信有更优雅的方式来做到这一点。据我所见,它sed非常强大,应该可以用一个sed命令来完成。

期待您的回答:-)

答案1

正如评论中所建议的那样,我尝试使用它xmlstarlet来解决这个问题,效果很好。这是我的脚本

xml ed -d '//item[not(contains(title,"Project Foo"))]' < sample_rss.xml

假设 feed 内容位于文件 中sample_rss.xml。该内容被输入到 中xml ed -d,这将删除与给定 XPath 表达式匹配的任何注释。XPath 表达式查找任何<item> 不包含<title>文本 的节点的注释"Project Foo"

这似乎效果很好,而且我对执行时间也很满意:

real    0m0.003s
user    0m0.001s
sys     0m0.002s

注意命名空间

如果您想让它与适当的 rss 或 atom 提要一起工作,您可能会注意到feed包含一个 XML 命名空间(xmlns)属性,就像 YouTube 中的这个示例一样:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom">
   ...
</feed>

那么,上面的脚本将不再起作用!修复它让我很头疼,但下面是如何让它正常工作:

xml ed -d '//_:entry[not(contains(_:title,"Project Foo"))]' < youtube_rss.xml

有关此命名空间问题的更多信息,请参见:http://xmlstar.sourceforge.net/doc/UG/ch05.html

相关内容