假設我有一個如下所述的 xml 文件,並且我想使用 unix 命令提取應用程式名稱、計算機和狀態標記值,並以逗號分隔的格式呈現。
XML 檔案:-
<?xml version="1.0" encoding="UTF-8"?>
<applications>
<application name="Adapter/Code1">
<service name="Code1.par">
<deploymentStatus>Success</deploymentStatus>
<serviceInstance name="Code1-One">
<machine>123</machine>
<status>Running</status>
</serviceInstance>
<serviceInstance name="Code1-Two">
<machine>456</machine>
<status>Running</status>
</serviceInstance>
</service>
</application>
<application name="Adapter/Code2">
<service name="Code2.par">
<deploymentStatus>Success</deploymentStatus>
<serviceInstance name="Code2-One">
<machine>123</machine>
<status>Running</status>
</serviceInstance>
<serviceInstance name="Code2-Two">
<machine>456</machine>
<status>Running</status>
</serviceInstance>
</service>
</application>
</applications>
輸出:-
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
您能幫我提供執行此活動的 unixcommand/shell 腳本嗎?
提前致謝! !
答案1
Python3.x 解決方案(帶有xml.etree.ElementTree模組):
import xml.etree.ElementTree as ET
tree = ET.parse("test.xml")
root = tree.getroot()
for app in root.findall('application'):
for m,s in zip(app.iter('machine'), app.iter('status')):
print("%s,%s,%s" % (app.get('name'), m.text, s.text))
輸出:
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
xmlstarlet+awk(用於對每個application
元素的子節點進行分組)解決方案:
xmlstarlet sel -t -v "//application/@name| .//machine/text()| .//status/text()" -n input.xml
| awk '/Adapter/{app=$0; r=app; c=0; next}
{ if(++c==2){ c=0; print r","$0; r=app } else { r=r","$0 }}'
輸出:
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
"//application/@name| .//machine/text()| .//status/text()"
- XPath表達式來取得所需的節點/Adapter/{app=$0; r=app; c=0; next}
- 捕獲每個application
名稱以進行進一步串聯
答案2
安裝希德爾並使用xpath。
我認為最好的觀點來自serviceInstance
:
xidel f.xml -e '//serviceInstance/string-join((../../@name, machine, status),",")'
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
答案3
使用xmlstarlet
循環遍歷每個serviceInstance
節點:
xmlstarlet sel -t \
-m '//application/service/serviceInstance' \
-v '../../@name' -o , \
-v 'machine' -o , \
-v 'status' -nl \
file.xml
這會匹配serviceInstance
節點,並且對於每個這樣的節點,它會提取name
其祖父母節點的屬性、machine
節點的值和status
節點的值。這些輸出之間有逗號 ( -o ,
) ,末尾有換行符 ( -nl
)。
您也可以從xq
(來自https://kislyuk.github.io/yq/):
xq -r '
.applications.application[] | ."@name" as $name |
.service.serviceInstance[] | [ $name, .machine, .status ] | @csv' file.xml
答案4
如果您有充分的理由不使用 xml 工具,則可以使用低階解析,只要您的應用程式像您的範例一樣簡單:
sed 's/<application name="\([^"]*\)">/\1/
Ta
h
d
:a
/<machine>/!d
G
N
s_.*<machine>\(.*\)</machine>\n\(.*\)\n.*<status>\(.*\)</status>.*_\2,\1,\3_' yourfile.xml