2017-01-11 97 views
-1

我有一個XML文件,我想解析成bash變量/數組。 我有限的Linux命令(busybox)可用,因爲我在一個NAS盒子上工作。bash將XML解析爲多維數組

我的XML文件是這樣的:

<?xml version="1.0" encoding="UTF-8"?> . 
<WEBCAMS> 
<CAM> 
      <DESCRIPTION>description for cam 1</DESCRIPTION> 
      <URL>http://myURLtoWebcam1/cam1/pic.jpg</URL> 
      <FILENAME>filename1</FILENAME> 
</CAM> 
<CAM> 
      <DESCRIPTION>description for cam 2</DESCRIPTION> 
      <URL>http://myURLtoWebcam2/cam2/pic.jpg</URL> 
      <FILENAME>filename2</FILENAME> 
</CAM> 
</WEBCAMS> 

我的bash到目前爲止腳本:

#!/bin/sh 
rdom() { local IFS=\> ; read -d \< E C ;} 
while rdom; do 
if [[ $E = DESCRIPTION ]]; then 
     counter=$((counter+1)) 
     declare cam$counter="$C" 
fi 

done < webcams.xml 

我希望得到像下面這樣的XML內容:

echo "Cam1 description: ${cam1[0]}"; ## should show: description for cam 1 
echo "Cam1 URL: ${cam1[1]}"; ## should show: http://myURLtoWebcam1/cam1/pic.jpg 
echo "Cam1 filename: ${cam1[2]}"; should show: filename1 

echo "Cam2 description: ${cam2[0]}"; ## should show: description for cam 2 
echo "Cam2 URL: ${cam2[1]}"; ## should show: http://myURLtoWebcam1/cam2/pic.jpg 
echo "Cam2 filename: ${cam2[2]}"; ## should show: filename2 

所以遠遠我只能將「DESCRIPTION」字段讀入bash變量。
任何想法如何將其他字段「URL」和「FILENAME」到我的數組/變量?由於我的NAS上有限的Linux命令,迄今爲止發現的解決方案並不適合或無法根據我的需要進行修改。

+0

等一下。你有busybox shell嗎,還是有bash? ('#!/ bin/sh'通常類似於busybox在使用它的系統上執行'ash';即使在它是符號鏈接到bash的系統上,雖然它被調用爲' sh')。如果你真的有bash,並且你想能夠使用bash-only語法,你的shebang應該是'#!/ bin/bash'。 –

+0

除此之外 - **完全**您在該系統上有哪些其他軟件?即使是在一個非常小的系統上,真正的XML解析器隱藏在某處(在解釋型語言運行庫(如Python)中,或者通過本地依賴項(如libxml2)安裝在shell可訪問的幫助程序中)並不罕見。使用這樣一個解析器的答案將會少得多錯誤發生(如果集成合作夥伴在*不應該發生變化時破壞它們*破壞他們的代碼中斷手寫的消費者非常煩人,並且有經驗的人傾向於對於要求嚴格分析XML的問題沒什麼耐心)。 –

+0

順便說一下,'IFS = \> read -d \

回答

0

如果XSLTPROC可用,您可以使用它 - 獎勵它是一個真正的XML解析器。

> xsltproc transform.xsl webcams.xml 

Cam1 description: description for cam 1 
Cam1 URL: http://myURLtoWebcam1/cam1/pic.jpg 
Cam1 filename: filename1 
Cam2 description: description for cam 2 
Cam2 URL: http://myURLtoWebcam2/cam2/pic.jpg 
Cam2 filename: filename2 

哪裏transform.xsl是

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="CAM"> 
    <xsl:variable name="i" select="position()" /> 
Cam<xsl:value-of select="$i"/> description: <xsl:value-of select="DESCRIPTION"/> 
Cam<xsl:value-of select="$i"/> URL: <xsl:value-of select="URL"/> 
Cam<xsl:value-of select="$i"/> filename: <xsl:value-of select="FILENAME"/> 
    </xsl:template> 


    <xsl:template match="/WEBCAMS"><xsl:apply-templates select="*"/> 
    <xsl:text> 
</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 
+0

我使用的是GNU bash,版本爲3.2.57(1)--release(i686-pc-linux-gnu),但是有限的命令。不幸的是沒有XML解析器。 – mfuerli

+0

Charles您對我的IFS使用情況的最新評論意味着什麼?特別是我不明白你的陳述:「沒有必要嘗試玩功能當地人或類似的東西」 – mfuerli

0

這似乎是工作......但還是1,5D維數組或逃避變量的方法讓我頭疼 - 見下文問題FOR內循環:

#!/bin/sh 
rdom() { local IFS=\> ; read -d \< E C ;} 
while rdom; do 
if [[ $E = DESCRIPTION ]]; then 
     counter0=$((counter0+1)) 
     declare -a cam$((counter0))[0]="$C" 
fi 

if [[ $E = URL ]]; then 
     counter1=$((counter1+1)) 
     declare -a cam$((counter1))[1]="$C" 
fi 

if [[ $E = FILENAME ]]; then 
     counter2=$((counter2+1)) 
     declare -a cam$((counter2))[2]="$C" 
fi 

done < webcams.xml 

echo "Cam1 description: ${cam1[0]}"; 
echo "Cam1 URL: ${cam1[1]}"; 
echo "Cam1 filename: ${cam1[2]}"; 

echo "Cam2 description: ${cam2[0]}"; 
echo "Cam2 URL: ${cam2[1]}"; 
echo "Cam2 filename: ${cam2[2]}"; 

但它仍然是不可能的內獲取值像循環:

for ((c=1; c<=$counter0; c++)) 
do 
     var=cam$c; 
     echo "Cam$c description: ${!var[0]}"; 
     echo "Cam$c URL: ${!var[1]}"; 
     echo "Cam$c filename: ${!var[2]}"; 
done 
+0

如果我這樣做,我會有一個數組的描述,一個數組的URL和一個文件名數組。這樣你*可以*平凡地擁有你的'for'循環。 –

+0

爲了我的目的,我需要爲每個凸輪陣列 - 每個數組包含3個字段:DESCRIPTION,URL和FILENAME。後來凸輪(陣列)的數量不同。 – mfuerli

+0

不同的聲音數量聽起來像是一個非常有說服力的理由,只有三個陣列的元素數量不同,而不是相反。 –