案例十5、格式化輸出xml文件

在工做中咱們多多少少都接觸過xml文件,它的格式很是有規律性,但讀起來由於有太多的標籤(<>),不能一目瞭然,就好比下面一段配置:bash

<configuration>
     <artifactItems>
          <artifactItem>
              <groupId>zzz</groupId>
              <artifactld>aaa</artifactld>
          </artifactItem>
          <artifactItem>
              <groupId>xxx</groupId>
              <artifactld>yyy</artifactld>
          </artifactItem>
</artifactItems>

本案例的需求是從上面的XML文本中提取groupId和artifactld,並輸出爲以下格式:ide

artifactItem:groupId:zzz
artifactItem:artifactld:aaa
artifactItem:groupId:xxx
artifactItem:artifactld:yyy


知識點一:關於XML的小常識函數

XML(Extensible Markup Language),中文叫作:可擴展標記語言。XML和HTML很像,都是一種標記語言。XML主要用來傳送以及攜帶數據信息,而不是用來展現的,因此讀起來就有點障礙。測試


有很多服務的配置文件就是一個XML文本,在XML文本中定義對應的配置,就好比本案例中示例文本就是一個配置文件。XML的做用主要在於存儲數據,它以純文本格式進行存儲,所以提供了一種獨立於軟件和硬件的數據存儲方法。這讓建立不一樣的應用程序能夠共享的數據變得更加容易。因爲XML文本的格式是固定的,不管是Windows、Linux或者MAC等其餘操做系統,均可以識別,因此它的兼容性很好。spa


有一點,咱們必需要知道,就是XML是一種不做爲的標記語言,即,它不像HTML須要被解析、執行而後展現漂亮的網頁,它存在的意義僅僅是結構化、存儲以及傳輸信息。操作系統


知識點二:截取文檔中兩個關鍵詞中間的行xml

需求是,把文本中包含abc和123中間的部分打印出來,假設abc在123上面。若是使用sed,一條命令便可實現:文檔

# sed -n '/abc/,/123/p' 1.txt

不過這樣依然有abc和123的行,要想去掉他們,也很簡單:get

# sed -n '/abc/,/123/p' 1.txt |sed '/abc/d;/123/d'

若是文本中有多個abc和123,則會同時把全部符合條件的行所有打印出來,下面提供一個比較笨的土方法,幫助練習邏輯思惟能力。it

mysed.sh

#!/bin/bash
#先獲取abc和123所在行的行號
egrep -n 'abc|123' 1.txt |awk -F ':' '{print $1}' > /tmp/line_number.txt

#計算一共有多少包含abc和123的行
n=`wc -l /tmp/line_number.txt|awk '{print $1}'`

#計算一共有多少對abc和123
n2=$[$n/2]

for i in `seq 1 $n2`
do
    #每次循環都要處理兩行,第一次是1,2,第二次是3,4,依此類推
    m1=$[$i*2-1]
    m2=$[$i*2]

    #每次遍歷都要獲取abc和123的行號
    nu1=`sed -n "$m1"p /tmp/line_number.txt`
    nu2=`sed -n "$m2"p /tmp/line_number.txt`

    #獲取abc下面一行的行號
    nu3=$[$nu1+1]

     #獲取123上面一行的行號
    nu4=$[$nu2-1]
    
    #用sed把abc和123中間的行打印出來
    sed -n "$nu3,$nu4"p 1.txt

    #便於分辨,添加分隔行符號
    echo "============="
done

提供一個測試的文本1.txt,內容以下:

alskdfkjlasldkjfabalskdjflkajsd
asldkfjjk232k3jlk2
alskk2lklkkabclaksdj
skjjfk23kjalf09wlkjlah lkaswlekjl9
aksjdf
123asd232323
aaaaaaaaaa
222222222222222222
abcabc12121212
fa2klj
slkj32k3j
22233232123
bbbbbbb
ddddddddddd

用sed處理,結果是:

# sed -n '/abc/,/123/p' 1.txt |sed '/abc/d;/123/d'
skjjfk23kjalf09wlkjlah lkaswlekjl9
aksjdf
fa2klj
slkj32k3j

用mysed.sh處理,結果是:

# sh mysed.sh 
skjjfk23kjalf09wlkjlah lkaswlekjl9
aksjdf
=============
fa2klj
slkj32k3j
=============


案例分析

1)首先要找到<artifactItem>和</artifactItem>中間的數據段,針對這部分數據進行分析

2)能夠找到XML文檔中包含<artifactItem>和</artifactItem>的行的行號,而後使用sed把這部份內容截取出來

3)處理截取出來的數據段,使用sed、awk截取關鍵詞以及對應的值


本案例參考腳本

#!/bin/bash
#按要求輸出XML內容,本腳本定製性較強,不可通用
#做者:
#日期:

#假設要處理的XML文檔名字爲test.xml
#獲取和所在的行號
grep -n 'artifactItem>' test.xml |awk '{print $1}' |sed 's/://' > /tmp/line_number.txt

#計算和的行一共有多少行
n=`wc -l /tmp/line_number.txt|awk '{print $1}'`

#定義獲取關鍵詞和其值的函數
get_value(){
    #$1和$2爲函數的兩個參數,即下一行和上一行的行號(這個操做在下面)
    #截取出和中間的內容,而後獲取關鍵詞(如groupId)和其對應的值,寫入/tmp/value.txt
    sed -n "$1,$2"p test.xml|awk -F '<' '{print $2}'|awk -F '>' '{print $1,$2}' > /tmp/value.txt

    #遍歷整個/tmp/value.txt文檔
    cat /tmp/value.txt|while read line
    do
        #x爲關鍵詞,如groupId
        #y爲關鍵詞的值
        x=`echo $line|awk '{print $1}'`
        y=`echo $line|awk '{print $2}'`
        echo artifactItem:$x:$y
    done
}

#因爲/tmp/line_number.txt是成對出現的,n2爲一共多少對
n2=$[$n/2]

#針對每一對,打印關鍵詞和對應的值
for j in `seq 1 $n2`
do
    #每次循環都要處理兩行,第一次是1,2,第二次是3,4,依此類推
    m1=$[$j*2-1]
    m2=$[$j*2]

    #每次遍歷都要獲取和的行號
    nu1=`sed -n "$m1"p /tmp/line_number.txt`
    nu2=`sed -n "$m2"p /tmp/line_number.txt`

    #獲取下面一行的行號
    nu3=$[$nu1+1]

     #獲取上面一行的行號
    nu4=$[$nu2-1]

    get_value $nu3 $nu4
done
相關文章
相關標籤/搜索