使用grep、awk或sed等shell工具解析xml文件。

9 浏览
0 Comments

使用grep、awk或sed等shell工具解析xml文件。

我有以下xml需要解析,并根据标签的值提取标签的值。仅在type == 'hosted'时提取。我希望使用bash工具如grep、sed和awk进行提取。在没有条件的情况下提取单个标签值是我以前做过的事情,但带有条件的提取是我以前没有做过的。我可以很容易地使用python或其他我熟悉的编程语言完成它。但如果能在shell脚本中完成,那将是理想的解决方案。

...
    
      hosted-npm
      hosted
    
    
      proxied-npm
      proxied
    
...

0
0 Comments

xmlstarlet是一个命令行XML工具包,可以将复杂的XSLT模板表达为一系列短命令行开关。以上内容展示了如何使用类似grep、awk或sed等shell工具解析xml文件。这里给出了一个例子,假设我们有一个格式良好的XML文档repos.xml,通过以下命令行将其通过XMLStarlet过滤器运行:

$ cat repos.xml | xmlstarlet sel -t -m '//repositories-item' \
                 -i 'type="hosted"' -v 'name' -n 

这将输出一行结果:

hosted-npm

下面我们来看一下XMLStarlet的命令行:

  1. 我们使用sel开关指定了选择模式的命令。
  2. 我们使用-t开关指定了选择模板。
  3. 我们使用-m开关将解析器限制为<repositories-item>元素。
  4. 我们使用-i开关选择具有"type"元素值为"hosted"的元素。
  5. 我们使用-v开关打印出"name"元素的值。
  6. 我们使用-n开关在每行输出之后打印一个换行符。

这是XMLStarlet生成的等价XSLT代码:

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">

<xsl:output omit-xml-declaration="yes" indent="no"/>

<xsl:template match="/">

<xsl:for-each select="//repositories-item">

<xsl:choose>

<xsl:when test="type=&quot;hosted&quot;">

<xsl:call-template name="value-of-template">

<xsl:with-param name="select" select="name"/>

</xsl:call-template>

<xsl:value-of select="'&#10;'"/>

</xsl:when>

</xsl:choose>

</xsl:for-each>

</xsl:template>

<xsl:template name="value-of-template">

<xsl:param name="select"/>

<xsl:value-of select="$select"/>

<xsl:for-each select="exslt:node-set($select)[position()&gt;1]">

<xsl:value-of select="'&#10;'"/>

<xsl:value-of select="."/>

</xsl:for-each>

</xsl:template>

</xsl:stylesheet>

根据Charles Duffy的建议,可以使用XMLStarlet的-C选项生成此XSLT规范:

xmlstarlet sel -C -t -m '//repositories-item' \
       -i 'type="hosted"' -v 'name' -n > hosted-repos.xslt

生成的XSLT规范可以直接与xsltproc一起使用:

cat repos.xml | xsltproc hosted-repos.xslt - 

可以向OP展示如何使用xsltproc应用这个XSLT,以确保他们了解在没有安装XMLStarlet的服务器上也可以使用这个解决方案。

0
0 Comments

使用Shell工具(如grep、awk或sed)解析xml的原因是缺乏专门的xml工具。在解决方法中,我们可以使用awk来处理这个问题,通过使用封闭标签来定义记录的分隔符。首先,我们可以使用以下命令来提取包含特定标签的内容:

$ awk -v RS='</?repositories-item>' '/<type>hosted<\/type>/' file

<name>hosted-npm</name>

<type>hosted</type>

请注意,这需要多字符的RS,而GNU awk支持这个功能。然后,我们可以使用以下命令来更好地控制匹配和输出内容:

$ awk -v RS='</?repositories-item>' -F'[<>]' '

{delete a;

for(i=2;i<=NF;i+=4) a[$i]=$(i+1);

if(a["type"]=="hosted") print a["name"] }' file

hosted-npm

通过以上方法,我们可以使用Shell工具来解析xml文件,提取所需的信息。

0