Linux Shell | 解析xml節點
- 2019 年 11 月 14 日
- 筆記
01 xml文件
# user.xml <user> <name>Toy</name> <sex>man</sex> <room/> </user> 其中第 5 行的<room/> xml 節點是空節點,是比較特殊的格式。
02 多條命令解析xml節點
採用多條命令和管道符也可以解析xml節點,方式如下:
[~]$ cat user.xml | grep name | sed 's/^.*<name>//g' | sed 's/</name>.*$//g' Toy [~]$ cat user.xml | grep name | sed 's/^.*<sex>//g' | sed 's/</sex>.*$//g' [~]$ cat user.xml | grep room | sed 's/^.*<room>//g' | sed 's/</room>.*$//g' <room/> 上面的方式無法解析 <room/> 這種特殊格式的 xml 節點,雖然用多個命令和管道符是可以實現解析正常格式的xml節點的值,但是過多的管道符是會降低執行效率的。
因為管道符是會為連接的命令產生子進程,從而加大CPU的開銷。
03 一行 awk 命令解析xml節點
awk 命令解析所有特殊的 xml 節點的值,只需要一行命:
[~]$ awk '/</*name/*>/{gsub(/[[:space:]]*</*name/*>/,"");print $0}' user.xml Toy [~]$ awk '/</*sex/*>/{gsub(/[[:space:]]*</*sex/*>/,"");print $0}' user.xml man [~]$ awk '/</*room/*>/{gsub(/[[:space:]]*</*room/*>/,"");print $0}' user.xml [~]$ 上面的 awk 方式可以兼容所有特殊的 xml 節點,並且只需要一條命令就能解析出 xml 的值。
簡單說明下命令的意思:
awk '/匹配的字元串/{print $0}'表示在文本中,找到匹配的字元串所在的行記錄,可以替代grep "匹配的字元串"gsub(/匹配的字元串/,"")是 awk 內部的函數,表示將匹配到的字元串替換成"",也就是替換成空字元串,可以替代sed 's/匹配的字元串//g'</*name/*>中的*號是正則表達式,*號表示可以重複前面字元 0 個或多個,所以</*name/*>可以間接的表示<name>、</name>和<name/>等[[:space:]]表示匹配空格、製表格等空白符,[[:space:]]*表示匹配空白字元0個或多個$0表示取記錄的所有記錄
所以,awk 解析 xml 節點的命令小結成如下:
awk '/</*節點名字/*>/{gsub(/[[:space:]]*</*節點名字/*>/,"");print $0}' xml文件 04 小結
我們在編寫腳本時,需要解析文本文件時,盡量避免使用多命令和管道符的方式去解析,因為使用了管道符就會產生子進程,會加大了 CPU 的開銷。
大部分情況下只需要一條 awk 命令就完成解析的工作,相比較起多命令和管道符的方式效率會更高,並且CPU開銷小。
通過以上的兩個解析xml節點的案例,我們可以總結出:
awk '/匹配的字元串/{print $0}' 可以替代 grep "匹配的字元串" awk '{gsub(/匹配的字元串/,"");print $0}' 可以替代 sed 's/匹配的字元串/""/g' awk '/匹配的字元串/{gsub(/匹配的字元串/,"");print $0}' <xml文件> 可以替代 cat <xml文件> | grep "匹配的字元串" | sed 's/匹配的字元串/""/g'
