我正在使用这个命令:
xmllint --xpath 'substring-after(string(//item/link), "_")' rss.xml
并获得所需的输出,但它位于第一个元素上。我将如何解决这个问题以将其应用于每个link
?
我愿意使用任何实用程序,只要接受示例输入并且可以使用一个表达式来获得所需的输出。
输入示例:
<rss version="2.0">
<channel>
<title>Malicious IPs | By Last Bad Event | Project Honey Pot</title>
<link><![CDATA[http://www.projecthoneypot.org/list_of_ips.php]]></link>
<description/>
<copyright>Copyright 2021 Unspam Technologies, Inc</copyright>
<language>en-us</language>
<lastBuildDate>July 03 2021 07:15:12 PM</lastBuildDate>
<image>
<url>http://www.projecthoneypot.org/images/small_phpot_logo.jpg</url>
<title>Project Honey Pot | Distribute Spammer Tracking System</title>
<link>http://www.projecthoneypot.org</link>
</image>
<item>
<title>92.204.241.167 | C</title>
<link>http://www.projecthoneypot.org/ip_92.204.241.167</link>
<description>Event: Bad Event | Total: 3,061 | First: 2021-03-27 | Last: 2021-07-03</description>
<pubDate>July 03 2021 07:15:12 PM</pubDate>
</item>
<item>
<title>181.24.239.244</title>
<link>http://www.projecthoneypot.org/ip_181.24.239.244</link>
<description>Event: Bad Event | Total: 1 | First: 2021-07-03 | Last: 2021-07-03</description>
<pubDate>July 03 2021 07:15:12 PM</pubDate>
</item>
<item>
<title>193.243.195.66 | S</title>
<link>http://www.projecthoneypot.org/ip_193.243.195.66</link>
<description>Event: Bad Event | Total: 4 | First: 2021-06-12 | Last: 2021-07-03</description>
<pubDate>July 03 2021 07:15:12 PM</pubDate>
</item>
</channel>
</rss>
期望的输出:
92.204.241.167
181.24.239.244
193.243.195.66
当前输出:
92.204.241.167
答案1
使用xmlstarlet
:
xmlstarlet sel -t -m '//item/link' -v 'substring-after(., "_")' -nl rss.xml
这首先匹配 ( -m
) 所有//item/link
节点,然后获取-v
与匹配节点值中第一个下划线字符后面的字符串关联的值 ( )。最终-nl
在每个结果字符串之间输出一个换行符。
substring-after()
将为集合中与第一个表达式匹配的每个节点计算第二个表达式 ( )。
答案2
实际上仅使用 XPath 1.0 无法实现这一目标。您无法返回字符串序列,因为 XPath 1.0 中没有此类数据类型,并且您无法返回连接各个子字符串的单个字符串,因为您仍然需要子字符串序列作为中间结果,并且同样,不存在这样的数据类型。因此,您要么需要迁移到 XPath 2.0+,要么需要执行多个 XPath 表达式的主机语言的一些帮助 - 这就是 @Kusalananda 的 xmlstarlet 解决方案正在做的事情。
然而,您使用的是命令行,因此有非常广泛的可用工具可供选择 - 您可以像使用 XPath 一样轻松地使用 XQuery,而且您当然不会局限于古老的 XPath 1.0 版本。例如,对于撒克逊人,你可以这样做
java net.sf.saxon.Query -qs:"//item/link!substring-after(., '_')" -s:rss.xml
这使用 XPath 3.0 和 XQuery 3.0 中可用的“bang”运算符,它将右侧的表达式应用于左侧表达式选择的每个项目。
答案3
我的希德尔是另一个运行现代 XPath 表达式的工具:
xidel rss.xml --xpath "//item/link/substring-after(., '_')"