如何使用 read 解析来自 rss xml 的额外属性
How to parse extra attribute from rss xml with read
我想解析来自 Jackett 的数据,最初我尝试使用 flexget,但我需要提取各种插件中不存在的数据,所以我开始使用这个小脚本来尝试解析那些额外的数据.
我的rss是这样的
<?xml version="1.0" encoding="UTF-8"?>
<rss version="1.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:torznab="http://torznab.com/schemas/2015/feed">
<channel>
<atom:link href="http://jackett:9117/" rel="self" type="application/rss+xml" />
<title>site description</title>
<description>A general italian tracker</description>
<link>https://site.some/</link>
<language>en-us</language>
<category>search</category>
<image>
<url>http://jackett:9117/logos/site.png</url>
<title>site description</title>
<link>https://site.some/</link>
<description>site description</description>
</image>
<item>
<title>Pinnacle Studio Ultimate v23 0 1 177 64 Bit Content Pack</title>
<guid>https://site.some/index.php?page=torrent-details&id=id</guid>
<jackettindexer id="site">site description</jackettindexer>
<comments>https://site.some/index.php?page=torrent-details&id=id</comments>
<pubDate>Mon, 26 Aug 2019 18:47:48 +0200</pubDate>
<size>4778150912</size>
<grabs>4</grabs>
<description />
<link>http://jackett:9117/dl/site/?jackett_apikey=apikey&path=Q2ZESjhIOTlRbnNBaTlsTXBueG41dVNtYWFqVjlsbTFockNDVXRieE5OYXRQYTdnclc4Zmc2dGJVNlFiQ01SVW9Wbm9yblJaZnhWXy0wSnVocHRISGxkYmNQLVQ5aWh6S1RORWtqMmwzMTlvTUFNZHlrV1c2czBlbjhNczlFa3VuQ1RxVjRsTkM0UGxRc2RUYzllR0tJaTBVMFFtMWc0UHIybnl0eFVkbGZqcUxuR1BPRDN0MGYwWUNNcVZ5d3NWazgta0Z0SkdrUUZIYnpZZWpUOTA1V2F5b1JGMEpTWlZVSzN0bVkzYzFMU09BLTlBck54bERpRU0yZ3lNTzkwcDU3amhNWE1MOXZmWFhLSEJaa1gwWEpWMHFYUFRfMFMtSlJQX05oalRMNmtpTlc4S0NueDF6c1VZazZfTkg0bE1IZFF5cEE&file=Pinnacle+Studio+Ultimate+v23+0+1+177+64+Bit+Content+Pack</link>
<category>4010</category>
<category>100007</category>
<enclosure url="http://jackett:9117/dl/site/?jackett_apikey=apikey&path=Q2ZESjhIOTlRbnNBaTlsTXBueG41dVNtYWFqVjlsbTFockNDVXRieE5OYXRQYTdnclc4Zmc2dGJVNlFiQ01SVW9Wbm9yblJaZnhWXy0wSnVocHRISGxkYmNQLVQ5aWh6S1RORWtqMmwzMTlvTUFNZHlrV1c2czBlbjhNczlFa3VuQ1RxVjRsTkM0UGxRc2RUYzllR0tJaTBVMFFtMWc0UHIybnl0eFVkbGZqcUxuR1BPRDN0MGYwWUNNcVZ5d3NWazgta0Z0SkdrUUZIYnpZZWpUOTA1V2F5b1JGMEpTWlZVSzN0bVkzYzFMU09BLTlBck54bERpRU0yZ3lNTzkwcDU3amhNWE1MOXZmWFhLSEJaa1gwWEpWMHFYUFRfMFMtSlJQX05oalRMNmtpTlc4S0NueDF6c1VZazZfTkg0bE1IZFF5cEE&file=Pinnacle+Studio+Ultimate+v23+0+1+177+64+Bit+Content+Pack" length="4778150912" type="application/x-bittorrent" />
<torznab:attr name="category" value="4010" />
<torznab:attr name="category" value="100007" />
<torznab:attr name="seeders" value="4" />
<torznab:attr name="peers" value="6" />
<torznab:attr name="minimumratio" value="1" />
<torznab:attr name="minimumseedtime" value="172800" />
<torznab:attr name="downloadvolumefactor" value="1" />
<torznab:attr name="uploadvolumefactor" value="1" />
</item>
</channel>
</rss>
所以最初我的第一个想法是解析每个部分以提取信息,所以我想到了这个
#!/bin/bash
xmlgetnext () {
local IFS='>'
read -d '<' TAG VALUE
}
# /data/Varie/Scripts/mmm
cat /data/Varie/Scripts/mmm | while xmlgetnext ; do
case $TAG in
'item')
title=''
link=''
description=''
downloadvolumefactor=''
;;
'title')
title="$VALUE"
;;
'link')
link="$VALUE"
;;
'downloadvolumefactor')
downloadvolumefactor="$VALUE"
;;
'/item')
cat<<EOF
------------------------------
Title: $title
Link: $link
Custom value: $downloadvolumefactor
------------------------------
EOF
;;
esac
done
所以 read 从第一个 < 开始读到下一个 < 然后设置 TAG 和 VALUE
直到这里对我来说没问题,问题是我找不到提取 downloadvolumefactor 的方法,因为该值的格式不符合标准。
我的第一个想法是在解析之前修改 rss,所以也许我可以用替换正则表达式进行转换
<torznab:attr name="uploadvolumefactor" value="1" />
进入
<downloadvolumefactor>1</downloadvolumefactor>
你有更好的主意吗?
使用 xml 感知工具。
xmllint --xpath 'string(//*[name()="torznab:attr" and @name="downloadvolumefactor"]/@value)' /data/Varie/Scripts/mmm
会 return:
1
不要使用正则表达式解析 xml 文件。
如果必须,当必须时,使用 awk
或 sed
或 [=15= 进行过滤会更容易] 与 cut
和类似的:
sed -nr '/.*<torznab:attr name="uploadvolumefactor" value="([^"]*).*/s///p' /data/Varie/Scripts/mmm
Bash 虽然读取循环非常慢,但最好使用其他工具。如果文件格式稳定并且您无法获得 xmllint
或其他 xml 感知工具,我会使用 sed
对其进行预处理 - 读取一行,从中提取信息,添加保持 space,继续阅读和解析直到遇到 </item>
。但是使用 xml 感知工具将更加安全且不易出错。
这是一个简单的 awk
(标准 Linux gnu awk 或 gawk)脚本,它解决了将输入文件扫描为纯文本的问题。
script.awk
match([=10=],"<title>[^<]*", arr) {title=substr(arr[0],8)} # read title line
match([=10=],"<link>[^<]*", arr) {link=substr(arr[0],7)} # read link line
match([=10=],/uploadvolumefactor" value="[^"]/, arr) {valueFactor=substr(arr[0],28)} # read valueFactor line
/<\/item>/ { # ouput values on item element termination
print "------------------------------";
print "Title: "title;
print "Link: "link;
print "Custom value: "valueFactor;
print "------------------------------";
}
运行:
awk -f script.awk input.xml
提供了问题中的input.xml
。
输出:
------------------------------
Title: Pinnacle Studio Ultimate v23 0 1 177 64 Bit Content Pack
Link: http://jackett:9117/dl/site/?jackett_apikey=apikey&path=Q2ZESjhIOTlRbnNBaTlsTXBueG41dVNtYWFqVjlsbTFockNDVXRieE5OYXRQYTdnclc4Zmc2dGJVNlFiQ01SVW9Wbm9yblJaZnhWXy0wSnVocHRISGxkYmNQLVQ5aWh6S1RORWtqMmwzMTlvTUFNZHlrV1c2czBlbjhNczlFa3VuQ1RxVjRsTkM0UGxRc2RUYzllR0tJaTBVMFFtMWc0UHIybnl0eFVkbGZqcUxuR1BPRDN0MGYwWUNNcVZ5d3NWazgta0Z0SkdrUUZIYnpZZWpUOTA1V2F5b1JGMEpTWlZVSzN0bVkzYzFMU09BLTlBck54bERpRU0yZ3lNTzkwcDU3amhNWE1MOXZmWFhLSEJaa1gwWEpWMHFYUFRfMFMtSlJQX05oalRMNmtpTlc4S0NueDF6c1VZazZfTkg0bE1IZFF5cEE&file=Pinnacle+Studio+Ultimate+v23+0+1+177+64+Bit+Content+Pack
Custom value: 1
------------------------------
我想解析来自 Jackett 的数据,最初我尝试使用 flexget,但我需要提取各种插件中不存在的数据,所以我开始使用这个小脚本来尝试解析那些额外的数据. 我的rss是这样的
<?xml version="1.0" encoding="UTF-8"?>
<rss version="1.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:torznab="http://torznab.com/schemas/2015/feed">
<channel>
<atom:link href="http://jackett:9117/" rel="self" type="application/rss+xml" />
<title>site description</title>
<description>A general italian tracker</description>
<link>https://site.some/</link>
<language>en-us</language>
<category>search</category>
<image>
<url>http://jackett:9117/logos/site.png</url>
<title>site description</title>
<link>https://site.some/</link>
<description>site description</description>
</image>
<item>
<title>Pinnacle Studio Ultimate v23 0 1 177 64 Bit Content Pack</title>
<guid>https://site.some/index.php?page=torrent-details&id=id</guid>
<jackettindexer id="site">site description</jackettindexer>
<comments>https://site.some/index.php?page=torrent-details&id=id</comments>
<pubDate>Mon, 26 Aug 2019 18:47:48 +0200</pubDate>
<size>4778150912</size>
<grabs>4</grabs>
<description />
<link>http://jackett:9117/dl/site/?jackett_apikey=apikey&path=Q2ZESjhIOTlRbnNBaTlsTXBueG41dVNtYWFqVjlsbTFockNDVXRieE5OYXRQYTdnclc4Zmc2dGJVNlFiQ01SVW9Wbm9yblJaZnhWXy0wSnVocHRISGxkYmNQLVQ5aWh6S1RORWtqMmwzMTlvTUFNZHlrV1c2czBlbjhNczlFa3VuQ1RxVjRsTkM0UGxRc2RUYzllR0tJaTBVMFFtMWc0UHIybnl0eFVkbGZqcUxuR1BPRDN0MGYwWUNNcVZ5d3NWazgta0Z0SkdrUUZIYnpZZWpUOTA1V2F5b1JGMEpTWlZVSzN0bVkzYzFMU09BLTlBck54bERpRU0yZ3lNTzkwcDU3amhNWE1MOXZmWFhLSEJaa1gwWEpWMHFYUFRfMFMtSlJQX05oalRMNmtpTlc4S0NueDF6c1VZazZfTkg0bE1IZFF5cEE&file=Pinnacle+Studio+Ultimate+v23+0+1+177+64+Bit+Content+Pack</link>
<category>4010</category>
<category>100007</category>
<enclosure url="http://jackett:9117/dl/site/?jackett_apikey=apikey&path=Q2ZESjhIOTlRbnNBaTlsTXBueG41dVNtYWFqVjlsbTFockNDVXRieE5OYXRQYTdnclc4Zmc2dGJVNlFiQ01SVW9Wbm9yblJaZnhWXy0wSnVocHRISGxkYmNQLVQ5aWh6S1RORWtqMmwzMTlvTUFNZHlrV1c2czBlbjhNczlFa3VuQ1RxVjRsTkM0UGxRc2RUYzllR0tJaTBVMFFtMWc0UHIybnl0eFVkbGZqcUxuR1BPRDN0MGYwWUNNcVZ5d3NWazgta0Z0SkdrUUZIYnpZZWpUOTA1V2F5b1JGMEpTWlZVSzN0bVkzYzFMU09BLTlBck54bERpRU0yZ3lNTzkwcDU3amhNWE1MOXZmWFhLSEJaa1gwWEpWMHFYUFRfMFMtSlJQX05oalRMNmtpTlc4S0NueDF6c1VZazZfTkg0bE1IZFF5cEE&file=Pinnacle+Studio+Ultimate+v23+0+1+177+64+Bit+Content+Pack" length="4778150912" type="application/x-bittorrent" />
<torznab:attr name="category" value="4010" />
<torznab:attr name="category" value="100007" />
<torznab:attr name="seeders" value="4" />
<torznab:attr name="peers" value="6" />
<torznab:attr name="minimumratio" value="1" />
<torznab:attr name="minimumseedtime" value="172800" />
<torznab:attr name="downloadvolumefactor" value="1" />
<torznab:attr name="uploadvolumefactor" value="1" />
</item>
</channel>
</rss>
所以最初我的第一个想法是解析每个部分以提取信息,所以我想到了这个
#!/bin/bash
xmlgetnext () {
local IFS='>'
read -d '<' TAG VALUE
}
# /data/Varie/Scripts/mmm
cat /data/Varie/Scripts/mmm | while xmlgetnext ; do
case $TAG in
'item')
title=''
link=''
description=''
downloadvolumefactor=''
;;
'title')
title="$VALUE"
;;
'link')
link="$VALUE"
;;
'downloadvolumefactor')
downloadvolumefactor="$VALUE"
;;
'/item')
cat<<EOF
------------------------------
Title: $title
Link: $link
Custom value: $downloadvolumefactor
------------------------------
EOF
;;
esac
done
所以 read 从第一个 < 开始读到下一个 < 然后设置 TAG 和 VALUE
直到这里对我来说没问题,问题是我找不到提取 downloadvolumefactor 的方法,因为该值的格式不符合标准。
我的第一个想法是在解析之前修改 rss,所以也许我可以用替换正则表达式进行转换
<torznab:attr name="uploadvolumefactor" value="1" />
进入
<downloadvolumefactor>1</downloadvolumefactor>
你有更好的主意吗?
使用 xml 感知工具。
xmllint --xpath 'string(//*[name()="torznab:attr" and @name="downloadvolumefactor"]/@value)' /data/Varie/Scripts/mmm
会 return:
1
不要使用正则表达式解析 xml 文件。
如果必须,当必须时,使用 awk
或 sed
或 [=15= 进行过滤会更容易] 与 cut
和类似的:
sed -nr '/.*<torznab:attr name="uploadvolumefactor" value="([^"]*).*/s///p' /data/Varie/Scripts/mmm
Bash 虽然读取循环非常慢,但最好使用其他工具。如果文件格式稳定并且您无法获得 xmllint
或其他 xml 感知工具,我会使用 sed
对其进行预处理 - 读取一行,从中提取信息,添加保持 space,继续阅读和解析直到遇到 </item>
。但是使用 xml 感知工具将更加安全且不易出错。
这是一个简单的 awk
(标准 Linux gnu awk 或 gawk)脚本,它解决了将输入文件扫描为纯文本的问题。
script.awk
match([=10=],"<title>[^<]*", arr) {title=substr(arr[0],8)} # read title line
match([=10=],"<link>[^<]*", arr) {link=substr(arr[0],7)} # read link line
match([=10=],/uploadvolumefactor" value="[^"]/, arr) {valueFactor=substr(arr[0],28)} # read valueFactor line
/<\/item>/ { # ouput values on item element termination
print "------------------------------";
print "Title: "title;
print "Link: "link;
print "Custom value: "valueFactor;
print "------------------------------";
}
运行:
awk -f script.awk input.xml
提供了问题中的input.xml
。
输出:
------------------------------
Title: Pinnacle Studio Ultimate v23 0 1 177 64 Bit Content Pack
Link: http://jackett:9117/dl/site/?jackett_apikey=apikey&path=Q2ZESjhIOTlRbnNBaTlsTXBueG41dVNtYWFqVjlsbTFockNDVXRieE5OYXRQYTdnclc4Zmc2dGJVNlFiQ01SVW9Wbm9yblJaZnhWXy0wSnVocHRISGxkYmNQLVQ5aWh6S1RORWtqMmwzMTlvTUFNZHlrV1c2czBlbjhNczlFa3VuQ1RxVjRsTkM0UGxRc2RUYzllR0tJaTBVMFFtMWc0UHIybnl0eFVkbGZqcUxuR1BPRDN0MGYwWUNNcVZ5d3NWazgta0Z0SkdrUUZIYnpZZWpUOTA1V2F5b1JGMEpTWlZVSzN0bVkzYzFMU09BLTlBck54bERpRU0yZ3lNTzkwcDU3amhNWE1MOXZmWFhLSEJaa1gwWEpWMHFYUFRfMFMtSlJQX05oalRMNmtpTlc4S0NueDF6c1VZazZfTkg0bE1IZFF5cEE&file=Pinnacle+Studio+Ultimate+v23+0+1+177+64+Bit+Content+Pack
Custom value: 1
------------------------------