2013-07-02 50 views
0

我想從這個XML例子我應該用BASH解析這個XML嗎?

<String Name="descResist"> 
    <Description><![CDATA["resist_type_chimney"]]></Description> 
    <Flags> 
     <ParFlg_Child/> 
    </Flags> 
    <Value><![CDATA["90_min."]]></Value> 
</String> 

descResist;resist_type_chimney 
descResist;90_min. 

所以,基本上我需要提取CDATA內容與名稱的值Concat的它得到。

其中一個問題是,它並不總是在標籤String ...可能是也IntegerTitleBoolean,等...

我想這

$ grep -o "Name=\".*\"\|<\!\[CDATA\[.*\]\]>" file.xml | sed 's/<\!\[CDATA\[\"\(.* \)\"\]\]>/\1/'

這給我

Name="descResist" 
resist_type_chimney 
90_min. 

我怎樣才能將下一行的值前綴名稱爲stri NG?

Name="descResist" 
resist_type_chimney 
90_min. 
Name="anotherName" 
foo_bar 
Name="anoooother" 
Name="notempty" 
bar_foo 

它變得有點複雜。

這也是很好的與XML這樣的工作嗎?也應該有任何嵌套<tagType Name=...所以我想這應該不成問題。

編輯:我的工作在Cygwin是正在尋找慶典/ SED/awk的簡單解決方案。

+0

檢查http://stackoverflow.com/questions/4680143/how-to-parse-xml-using-shellscript – anishsane

回答

2

嘗試了這一點:

#!/bin/bash 

Name="InvalidName" 
while read line; do 
     case "$line" in 
       Name=*) eval "$line" ;; # assuming $line is always bash-friendly Name="Value" 
       *) echo "$Name;$line" ;; 
     esac 
done < <(egrep -o 'Name=".*"|<!\[CDATA\[.*?\]\]>' file.xml | sed -r 's/<!\[CDATA\["(.*)"\]\]>/\1/') 

我稍微改變了你的命令的使用擴展正則表達式(這就是爲什麼它的「egrep的」和「SED -r」),所以這是一個有點更容易閱讀。

我不喜歡的eval我用,但「出口-n」做了奇怪這種情況下,代碼會得到不必要的複雜性只是爲了避免EVAL。

這是確定以「解析」的XML中的Bash如果你真的真的確定文本結構不會改變。只要有人決定通過將所有內容摺疊成一行來「優化」XML,您就有點敬酒。

編輯

這裏有沒有醜陋的eval的腳本:

#!/bin/bash 

Name="InvalidName" 
while read line; do 
     case "$line" in 
       Name=*) export -n "$line" ;; # assuming $line is always bash-friendly Name=Value 
       *) echo "$Name;$line" ;; 
     esac 
done < <(egrep -o 'Name=".*"|<!\[CDATA\[.*?\]\]>' file.xml | sed -r 's/<!\[CDATA\["(.*?)"\]\]>/\1/; s/Name="(.*)"/Name=\1/') 
+0

不錯,這看起來比我的解決方案更好。但我不太喜歡那個eval(和你一樣)。 – bartimar

2

我建議使用解析器。這裏有一個使用XML::Twig示例。

內容script.pl

#!/usr/bin/env perl 

use warnings; 
use strict; 
use XML::Twig; 

my $twig = XML::Twig->new(
     twig_handlers => { 
       '//*[@Name]' => sub { 
         for my $d ($_->descendants('#CDATA')) { 
           (my $t = $d->text) =~ s/\A"(.*)"\z/$1/; 
           printf qq|%s;%s\n|, $_->att('Name'), $t; 
         } 
       }, 
     } 
)->parsefile(shift); 

運行它想:

perl script.pl xmlfile 

國債收益率:

descResist;resist_type_chimney 
descResist;90_min. 
+0

我無法在cygwin上使用perl,並且真正在尋找bash/sed/awk解決方案。但thx – bartimar

+0

看看http://perldoc.perl.org/perlcygwin.html。不直截了當,但可能有所幫助。 – anishsane

+0

我無法安裝任何東西,這是問題:) – bartimar