簡體   English   中英

使用ksh腳本從XML中提取數據

[英]Extract data from XML using ksh script

由於缺乏信息,我就此主題提出的第一個問題已經結束。 所以再添一些細節再問這個問題。

我必須從xml文件中提取一個標簽中給出的值,我必須使用ksh(我可以在perl中解決這個問題,但我必須使用ksh,不能使用像xmlsh這樣的第三方工具)

sample.xml中

<?xml version="1.0" standalone="yes" ?>
<parent_one>
  <parent_two>
    <Pool>
      <pool_name>ABC</pool_name>
      <percent_full>79</percent_full>
      <pool_state>Enabled</pool_state>
    </Pool>
    <Pool>
      <pool_name>DEF</pool_name>
      <percent_full>40</percent_full>
      <pool_state>Enabled</pool_state>
    </Pool>
    <Pool>
      <pool_name>XYZ</pool_name>
      <percent_full>40</percent_full>
      <pool_state>Disabled</pool_state>
    </Pool> 
    <Totals>
      <total_tracks>4546456</total_tracks>
      <percent_full>48</percent_full>
    </Totals>
  </parent_two>
</parent_one>

ksh腳本應該讀取sample.xml並從pool_name標記打印ABC,DEF,因為相應的pool_state標記已啟用。 它不應該打印XYZ,因為它的pool_state標記被禁用。

ksh腳本將讀取sample.xml並輸出以下內容

ABC

DEF

這在ksh中是可行的還是我必須使用perl?

我用(n)awk完成了很多奇數格式文件的解析。 從技術上講,這可以用ksh完成,但是awk(和perl)更容易......

以下示例使用awk中的startend構造,該構造僅處理開始結束模式之間的行。 (在本例中為<Pool></Pool> 。)

除此之外,它是直截了當的,使用變量來模仿xml元素以便清晰。

awk '/<Pool>/,/<\/Pool>/ {
    if (/<pool_state>/) {
        pool_state=(/<pool_state>Enabled<\/pool_state>/)
    }
    if (/<pool_name>/) {
        if ( gsub(/.*<pool_name>|<\/pool_name>.*/,"") ) {
          pool_name=$0
        }
    }
    if (/<\/Pool>/) {
      if (pool_name && pool_state)
        print pool_name
      unset pool_name
      unset pool_state
    }
}' sample.xml

當xml格式錯誤,多個Pool元素列在一行上時,此代碼將失敗。

這個問題的理智解決方案是調用xmllint --xpathxqilla -p或您xqilla -p Python / Ruby / Perl等XML庫。

否則,您可以查看Roland Mainz的XML示例並將其擴展用於您的目的。

如果您對此非常認真,那么您可能希望研究為libhml2編寫綁定以獲取ksh。 我認為還沒有人這樣做過。

話雖如此(我的評論是關於嘗試在沒有適當的XML解析器的情況下解析XML),讓我們使用sed / awk,而不是純粹的ksh。 以此答案為基礎,刪除將pool_state設置為Disabled所有<Pool></Pool>塊,然后獲取包含pool_name的行並捕獲標記之間的值。 如果您的xml文件看起來像您的樣本,這應該可以工作,但如果沒有,肯定會破壞。

awk '
    /<Pool>/ { rec=""; f=1 }
    f {rec = rec $0 ORS}
    /<\/Pool>/ {
        if (f && (rec !~ "<pool_state>Disabled</pool_state>"))
            printf "%s", rec
            f=0
    }' sample.xml |
grep pool_name |
sed 's#.*>\([^<]*\)<.*#\1#g'

你可以把整個東西放到一個awk腳本中,但我認為這可能更容易理解(好吧,我很懶)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM