使用bash解析日志文件中的数据?

时间:2017-08-28 17:45:04

标签: bash sed grep

我的日志文件如下所示:

<lun compNum="3" partitionNum="1" failed="1" backup="1" free_mem="1024" max_mem="2048" />
<lun compNum="22" partitionNum="11" failed="1" backup="0" free_mem="1024" max_mem="2048" />

我想要一个输出遍历所有这些行并将compNumparitionNum保存到此中:

PAIR=($compNumValue parititonNumValue)

不使用任何外部库并且仅使用本机bash的解决方案将是理想的。知道如何开始为bash的新手开始吗?

1 个答案:

答案 0 :(得分:4)

错误的方式(你所要求的)

lun_re='<lun compNum="([[:digit:]]+)" partitionNum="([[:digit:]]+)"[^/]* />'
while IFS= read -r line; do
  if [[ $line =~ $lun_re ]]; then
    compNum=${BASH_REMATCH[1]}
    partitionNum=${BASH_REMATCH[2]}
    echo "Read a line with compNum $compNum and partitionNum $partitionNum"
  fi
done

请参阅:

正确的方式

在读取XML时使用XML解析器。 <强>真即可。其他任何东西都不知道如何处理注释,命名空间,CDATA部分,甚至是简单的更改,比如生成此日志的程序的新版本将所有元素放在同一行上(或者在属性之间添加换行符,甚至只是更改属性以使partitionNum之前有partNum

在这种情况下,可能如下所示:

while IFS='|' read -r -d '' compNum partitionNum; do
  echo "Read a line with compNum $compNum and partitionNum $partitionNum"
done < <(xmlstarlet sel -t -m '//lun[@compNum][@partitionNum]' \
           -v ./@compNum -o '|' \
           -v ./@partitionNum -n)

除了上面给出的链接之外,请参阅BashFAQ #24以了解正在使用< <(...)语法的原因。

如果您没有在运行它的系统上安装XMLStarlet,您可以生成XSLT模板并使用xsltproc对其进行评估。 xmlstarlet -C发出以下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="//lun[@compNum][@partitionNum]">
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="./@compNum"/>
      </xsl:call-template>
      <xsl:text>|</xsl:text>
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="./@partitionNum"/>
      </xsl:call-template>
      <xsl:value-of select="'&#10;'"/>
    </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>

...这样您就可以使用xsltproc /path/to/template.xslt -作为给定xmlstarlet命令的等效内容。