从自定义xml中提取字段

时间:2017-11-09 11:21:53

标签: xml linux bash shell

我正在制作一个脚本来从XML中提取字段,现在我得到了这个,我需要让它工作,我正在尝试2 for和greps,我需要一些帮助这个

#! /bin/bash

function charge_files () {
XML="Prueba.xml";
if [ -f "$XML" ]; then
echo "=============================";
echo "| XML CHARGED |";
echo "=============================";
else
echo "=============================";
echo "| XML NOT CHARGED |";
echo "=============================";
fi
}

function extract () {
#extract all from the file (not curr working)
x=`grep "Host"`
for $x in "$XML"
do
for LINEA in `cat $XML | grep "<Telegram" ` #LINEA guarda el resultado del fichero datos.txt
do
TIMESTAMP=`echo $LINEA | grep [Timestamp="*"] ` #Extracts TIMESTAMP
FRAMEFORMAT=`echo $LINEA | grep [FrameFormat="*"]` #Extracts FRAMEFORMAT
RAWDATA=`echo $LINEA | grep [RawData="*"]` #Extracts RAWDATA

echo "$x $HOST $TIMESTAMP $FRAMEFORMAT $RAWDATA" >> output.logs #Shows result
done
done
}

charge_files
extract

我用这个字段获得了这个xml

 <CommunicationLog xmlns="http://knx.org/xml/telegrams/01">
  <RecordStart Timestamp="" Mode="" Host="PC1" ConnectionName="" ConnectionOptions="" ConnectorType="" MediumType="" />
  <Telegram Timestamp="" Service="" FrameFormat="" RawData="" />
  <Telegram Timestamp="" Service="" FrameFormat="" RawData="" />

  <RecordStart Timestamp="" Mode="" Host="PC2" ConnectionName="" ConnectionOptions="" ConnectorType="" MediumType="" />
  <Telegram Timestamp="" Service="" FrameFormat="" RawData="" />
  <Telegram Timestamp="" Service="" FrameFormat="" RawData="" />
  <RecordStop Timestamp="" />
</CommunicationLog>

我想要这样的输出来进行更多的比较:

HOST="PC1" ConnectorType="" Timestamp="" FrameFormat="" RawData=""
HOST="PC1" ConnectorType="" Timestamp="" FrameFormat="" RawData=""

HOST="PC2" ConnectorType="" Timestamp="" FrameFormat="" RawData=""
HOST="PC2" ConnectorType="" Timestamp="" FrameFormat="" RawData=""

1 个答案:

答案 0 :(得分:0)

代码存在许多问题。

  • 一般:
    • 缩进代码,使您和其他人更容易调试和支持代码。
    • 编写脚本时,每行几乎都行,并测试每一行。添加变量的回声,......
    • 不要写一大堆行,然后试着弄清楚它为什么不起作用。
    • 实施例。 extract()中的第一行不起作用。如果你只用那一行尝试extract(),不要前进,先调试。
  • Prueba.xml:
    • 你有一个RecordStart,然后是另一个RecordStart,而不是RecordStop。您是否忘记了第一个RecordStart的RecordStop?
    • 我添加了测试数据,因为使用空字段很难调试。
  • charge_files:
    • 除了检查文件是否存在外别无其他。但很好。
    • 不需要&#39;;&#39;关于echo命令或XML赋值。除去。
    • 如果XML文件不存在,您的脚本将无论如何都会运行。我添加了一个退出,因为该文件的其余部分需要存在该文件。
  • 提取物:

    • 你不能像你想做的那样使用for迭代线。因为将迭代每个单词。像我放入我的代码一样使用while。
    • 你需要循环每一行,看看我的代码。使用grep Telegram的方法无法区分PC1的Telegram线路和PC2的Telegram线路。
    • grep命令返回整行。因此,如果你对一行中的单词进行grep,它将不返回该行的一部分,它将返回整行。
    • 要提取一行的部分,你可以使用cut(就像我的要求一样简单),awk,sed。
  • 假设:

    • 这些行始终包含相同的信息,顺序相同。

所以这是我用于测试的XML文件:

 <CommunicationLog xmlns="http://knx.org/xml/telegrams/01">
  <RecordStart Timestamp="" Mode="" Host="PC1" ConnectionName="name1" ConnectionOptions="option1" ConnectorType="type1" MediumType="med1" />
  <Telegram Timestamp="t1a" Service="s1a" FrameFormat="ff1a" RawData="rd1a" />
  <Telegram Timestamp="t1b" Service="s1b" FrameFormat="ff1b" RawData="rd1b" />

  <RecordStart Timestamp="" Mode="" Host="PC2" ConnectionName="name2" ConnectionOptions="option2" ConnectorType="type2" MediumType="med2" />
  <Telegram Timestamp="t2a" Service="s2a" FrameFormat="ff2a" RawData="rd2a" />
  <Telegram Timestamp="t2b" Service="s2b" FrameFormat="ff2b" RawData="rd2b" />
  <RecordStop Timestamp="stoptimestamp" />
</CommunicationLog>

这里是剧本:

#! /bin/bash

function charge_files ()
{
    XML="Prueba.xml"
    if [ -f "$XML" ]; then
        echo "============================="
        echo "| XML CHARGED |"
        echo "============================="
    else
        echo "============================="
        echo "| XML NOT CHARGED |"
        echo "============================="
        exit 1
    fi
}

function extract ()
{
    host=''

    while IFS= read -r line; do
        # Find if it is a RecordtStart line
        if [ $(echo $line | grep -c "RecordStart") -eq 1 ]
        then
            # If host == '', then it is the first host we see.
            # Otherwise, we are changing host, so print an empty line
            if [ "$host" != '' ]
            then
                echo ""
            fi

            # Collect the host information
            host=$(echo $line | awk '{print $4}' | cut -d'"' -f2)

            # Collect the ConnectorType information
            connectortype=$(echo $line | awk '{print $7}')

            # Done with this loop in the while, move on to the next
            continue
        fi

        # Find if it is a Telegram line
        if [ $(echo $line | grep -c "Telegram") -eq 1 ]
        then
            # Collect the Timestamp information
            timestamp=$(echo $line | awk '{print $2}')

            # Collect the FrameFormat information
            frameformat=$(echo $line | awk '{print $4}')

            # Collect the RawData information
            rawdata=$(echo $line | awk '{print $5}')

            # Print the information
            echo "HOST=\"$host\" $connectortype $timestamp $frameformat $rawdata"

            # Done with this loop in the while, move on to the next
            continue
        fi

    done <$XML
}

charge_files
extract

产生了这个输出:

=============================
| XML CHARGED |
=============================
HOST="PC1" ConnectorType="type1" Timestamp="t1a" FrameFormat="ff1a" RawData="rd1a"
HOST="PC1" ConnectorType="type1" Timestamp="t1b" FrameFormat="ff1b" RawData="rd1b"

HOST="PC2" ConnectorType="type2" Timestamp="t2a" FrameFormat="ff2a" RawData="rd2a"
HOST="PC2" ConnectorType="type2" Timestamp="t2b" FrameFormat="ff2b" RawData="rd2b"