我想编写一个脚本:
- 接受一些 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