【问题标题】:Bash script and xml/rss parsingBash 脚本和 xml/rss 解析
【发布时间】:2012-05-20 01:59:45
【问题描述】:

我正在编写一个使用 xmllint 解析 rss 的小脚本。

现在我使用以下命令获取标题列表:

ITEMS=`echo "cat //title" | xmllint --shell rss.xml `
echo $ITEMS > tmpfile

但它返回:

<title>xxx</title> ------- <title>yyy :)</title> ------- <title>zzzzzz</title>

没有换行符或空格。 现在我只对标题标签的文本内容感兴趣,如果可能的话,我想使用 for/while 循环浏览标题,例如:

for  val in $ITEMS 
do
       echo $val
done

如何做到这一点? 提前致谢

【问题讨论】:

  • 不要成为受虐狂,使用脚本语言,如 python、ruby、世界上任何其他语言、perl(按优先顺序:P)
  • @KurzedMetal 你可以在 bash 中进行大量的解析、拆分和迭代。
  • 你会发现引用你的变量会有很大帮助:for val in "$ITEMS"; do echo "$val"; done
  • 谢谢,它可能会有所帮助,但如果我尝试这样做,“$val”包含整个字符串并且循环只运行一次,但它会使用正确的换行符打印 $val。我需要逐行阅读 $ITEMS,我该怎么做?
  • xmllint --xpath '//title/text()' rss.xml 有问题吗?

标签: xml bash parsing xml-parsing xmllint


【解决方案1】:

我在某些时候有相同类型的需求来解析 bash 中的 xml。我最终使用了您可能能够安装的 xmlstarlet http://xmlstar.sourceforge.net/。

如果没有,类似的东西会删除周围的标签:

echo "cat  //title/text()" | xmllint --shell  rss.xml

然后你需要在管道之后清理输出,一个基本的解决方案是:

echo "cat  //title/text()" | xmllint --shell  rss.xml  | egrep '^\w'

希望对你有帮助

【讨论】:

    【解决方案2】:

    要回答您的第一个问题,$ITEMS 与 echo 的未引用使用正在消除您的换行符。试试

    ITEMS=`echo "cat //title" | xmllint --shell rss.xml `
    echo "$ITEMS" > tmpfile
    #----^------^--- dbl-quotes only
    

    一般来说,使用for 循环最好留给不会生成意外空格或其他不可打印字符的项目。 (非字母数字),例如 for i in {1..10} ; do echo $i; done

    而且你真的不需要变量或临时文件,试试

      echo "cat //title" | xmllint --shell rss.xml |
      while read line ; do
          echo "$line"
      done
    

    根据您的 rrs 提要中的内容,您还可以从更改读取 cmd 使用的默认 IFS(内部字段分隔符)中受益,尝试

    while IFS= read line ....
    # or 
    while IFS="\n" read line
    # or
    while IFS="\r\n" read line
    

    我不确定你想通过echo "cat //title" | 进入 xmllint 来实现什么,所以我将其保留原样。这是对 xmllint 的指令吗?还是通过创建文档标题? (现在没有 xmllint 可以体验)。

    另外,你可能想看看reading rss feeds with awk,但它的级别相当低。

    我希望这会有所帮助。

    【讨论】:

    • yes 是对 xmllint 的说明,请检查我是否更新了问题,因为我注意到我提供的示例中缺少一些字符。谢谢:D
    • 我看不出您的新帖子与我用作您的主要命令的内容有什么不同。是在 cmd 中还是在您的示例当前输出中发生了变化? 我也在对我的答案进行编辑,请稍后再回来查看。祝你好运。
    【解决方案3】:

    除了Philippe's answer,如果你想直接从命令如cURL获取xml输出,你可以使用another file descriptor 进行管道传输。

    事实上,xmllintt shell 输入已经使用了 STDIN。下面是一个工作示例(只需记住将 URL 参数替换为您的)。

    # Create a temporary file and use it as third fd
    exec 3<> $(tempfile) &&
    # cURL the RSS URL and redirect STDOUT to the 3rd fd
    curl https://your-url/to/some/rss.xml >&3 &&
    # Then read  fd 3 with xmllint
    xmllint --format --shell /dev/fd/3 <<< 'cat //title/text()' | egrep '^\w' &&
    # Close the temporary file (remember global warming issues)
    exec 3>&-
    

    【讨论】:

      猜你喜欢
      • 2017-06-10
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      相关资源
      最近更新 更多