awk双引号字段分隔符

时间:2017-01-29 00:40:46

标签: python xml xslt awk

我似乎无法弄清楚我的最后一篇文章是否能实现我想要的输出。

我有一个包含许多条目的文件,如下所示:

<Stats>
    <RecNum>45435</RecNum>
    <Date>2016/12/31</Date>
    <DayofWeek>6</DayofWeek>
    <Time>16:35</Time>
    <Dir>Closing</Dir>
    <Class>2</Class>
    <SpeedSpan>1</SpeedSpan>
    <TimeSpan>1</TimeSpan>
    <Bucket Speed="34" Count="1"/>
    <Bucket Speed="35" Count="0"/>
    <Bucket Speed="36" Count="1"/>
</Stats>

如果Count = 1,我想打印日期,时间和速度,如下所示:

2016/12/31  16:35   34
2016/12/31  16:35   36

我最接近的是:

$ awk -F'[ <>]' 'BEGIN {d="d";t="t";} /<Date>/ {d=$3;} /<Time>/ {t=$3;} /Count="1"/ {print d "\t" t "\t" $3;}' speed.xml

这给了我:

2016/12/31  16:35   Speed="34"
2016/12/31  16:35   Speed="36"

我尝试了很多不同的迭代,但是如果没有措辞,似乎无法获得速度数。我试图使用“作为字段分隔符,但它似乎永远不会按预期工作。

希望找到一个awk解决方案,但如果没有,我总是可以使用python程序来删除不需要的字符。

3 个答案:

答案 0 :(得分:4)

Jose Ricardo Bustos M.'s helpful XSLT-based answerStephen Rauch's helpful Python-based answer是首选,因为它们采用适当的XML解析,这种解析更灵活,更健壮。

修复awk命令:

awk -v OFS='\t' -F'[<>]' '
  /<Date>/ {d=$3}
  /<Time>/ {t=$3} 
  /Count="1"/ {
    split($0, flds, "\"")
    print d, t, flds[2]
  }
' speed.xml

split($2, flds, "\"")将感兴趣的行拆分为",并将结果存储在自定义数组flds中,这允许通过索引2提取"Speed"属性值。

还要注意使用-v OFS='\t' - 即将输出字段分隔符设置为选项卡 - 这会启用更简单的print语句,枚举(,)输出字段,依赖在awk上隐式将它们与OFS分开。

事后补充:将"添加到字段分隔符字符集中也会有效:

awk -v OFS='\t' -F'["<>]' '
  /<Date>/ {d=$3}
  /<Time>/ {t=$3} 
  /Count="1"/ { print d, t, $3 }
' file

答案 1 :(得分:3)

虽然我喜欢awk,但我建议使用xslt来执行此操作(使用XSLT,您可以将XML文档转换为任何文本格式)。 xslt w3schools

  

file.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <xsl:for-each select="Stats/Bucket[@Count='1']">
            <xsl:value-of select="../Date"/>
            <xsl:text>&#x9;</xsl:text>
            <xsl:value-of select="../Time"/>
            <xsl:text>&#x9;</xsl:text>
            <xsl:value-of select="@Speed" />
            <xsl:text>&#xa;</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

运行它。如果您正在使用某种Linux / Unix,请使用XSLT-1.0处理器xsltproc(还有更多),如下所示:

xsltproc file.xsl file.xml

你明白了,

2016/12/31  16:35   34
2016/12/31  16:35   36

答案 2 :(得分:2)

因为你提到了python:

setNeedsLayout()

使用的数据:

import xml.dom.minidom

# Open XML document using minidom parser
DOMTree = xml.dom.minidom.parseString('<X>' + my_xml + '</X>')
collection = DOMTree.documentElement
for record in collection.getElementsByTagName("Stats"):
    date = record.getElementsByTagName('Date')[0].childNodes[0].data
    time = record.getElementsByTagName('Time')[0].childNodes[0].data
    buckets = record.getElementsByTagName('Bucket')
    for bucket in buckets:
        x = bucket.getAttribute('Count')
        if int(bucket.getAttribute('Count')) != 0:
            print('%s\t%s\t%s' % (date, time, bucket.getAttribute('Speed')))

打印:

my_xml = """
    <Stats>
        <RecNum>45435</RecNum>
        <Date>2016/12/31</Date>
        <DayofWeek>6</DayofWeek>
        <Time>16:35</Time>
        <Dir>Closing</Dir>
        <Class>2</Class>
        <SpeedSpan>1</SpeedSpan>
        <TimeSpan>1</TimeSpan>
        <Bucket Speed="34" Count="1"/>
        <Bucket Speed="35" Count="0"/>
        <Bucket Speed="36" Count="1"/>
    </Stats>
"""