2014-01-27 107 views
2

我目前正在寫一個外殼腳本,其讀取Vagrantfile和引導程序它(簡而言之;))殼牌腳本 - 從文件提取AWK塊分割成陣列

但我擊中下面片的壁的代碼:

TEST=() 
while read result; do 
    TEST+=(`echo ${result}`) 
done <<< `awk '/config.vm.define[ \s]\"[a-z]*\"[ \s]do[ \s]\|[a-zA-Z_]*\|/, /end/ { print }' Vagrantfile` 

echo "${TEST[1]}" 

當我通過Vagrantfile與兩臺機器此AWK圖案在正則表達式定義它(config.vm.define)被發現。

輸出

config.vm.define "web" do |web| 

web.vm.box  = "CentOs" 
web.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130731.box" 
web.vm.hostname = 'dev.local' 

web.vm.network :forwarded_port, guest: 90, host: 9090 
web.vm.network :private_network, ip: "22.22.22.11" 

web.vm.provision :puppet do |puppet| 
    puppet.manifests_path = "puppet/manifests" 
    puppet.manifest_file = "web.pp" 
    puppet.module_path = "puppet/modules" 
    puppet.options  = ["--verbose", "--hiera_config /vagrant/hiera.yaml", "--parser future"] 
end 
config.vm.define "db" do |db_mysql| 

db_mysql.vm.box  = "CentOs" 
db_mysql.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130731.box" 
db_mysql.vm.hostname = 'db.mysql.local' 

db_mysql.vm.network :private_network, ip: "22.22.22.22" 
db_mysql.vm.network :forwarded_port, guest: 3306, host: 3306 

db_mysql.vm.provision :puppet do |puppet| 
    puppet.manifests_path = "puppet/manifests" 
    puppet.manifest_file = "db.pp" 
    puppet.module_path = "puppet/modules" 
    puppet.options = ["--verbose", "--hiera_config /vagrant/hiera.yaml", "--parser future"] 
end 

但我似乎無法將它們傳遞到一個數組很好。我想要的是TEST數組包含兩個帶有機器config.vm.define塊的索引作爲它們的對應值。

E.g.

TEST[0] = 'config.vm.define "web" do |web| 

.... [REST OF THE BLOCK CONTENT] ... 

end' 

TEST[1] = 'config.vm.define "db" do |db_mysql| 

.... [REST OF THE BLOCK CONTENT] ... 

end' 

輸出echo "${TEST[1]}"nothing。如上圖所示,echo "${TEST[0]}"返回整個塊。

我玩IFS/RS/FS,但我似乎無法得到我想要的輸出。

+0

awk命令本身的確切輸出是什麼?在你的例子中,echo「$ {TEST [1]}」的結果是什麼? – grebneke

+0

每個'config.vm.define'塊中是否有換行符? –

+0

@grebneke更新了輸出問題 是的,有新行 – cocheese

回答

2

的溶液可能是兩個塊寫至兩個獨立的文件(blk1blk2)爲:

awk ' 
    /config.vm.define[[:space:]]\"[a-z]*\"[[:space:]]do[[:space:]]\|[a-zA-Z_]*\|/{f=1; i++} 
    f{print $0 > "blk"i} 
    /end/ {f=0}' Vagrantfile 

再後來讀取這兩個文件到bash的數組作爲

IFS= TEST=($(cat <"blk1") $(cat <"blk2")) 

備註:

  • 該reg ex \s似乎只適用於最新版本的gawk(適用於版本4.1,但不適用於版本3.1.8。
  • 對於gawk版本3.1.8,請改爲使用[[:space:]]
  • 對於gawk版本4.1,正則表達式\s不支持括號內的[\s]。二者必選其一config.vm.define[[:space:]]config.vm.define\s ..

更新

另一種可能是插入塊之間的人爲分隔,比如字符串@@@。那麼你可以做

IFS= TEST=() 
while IFS= read -r -d '@' line ; do 
    TEST+=($line) 
done < <(awk ' 
    /config.vm.define[[:space:]]\"[a-z]*\"[[:space:]]do[[:space:]]\|[a-zA-Z_]*\|/{f=1; i++} 
    f{print } 
    /end/ {f=0; print "@@@"}' Vagrantfile) 
+0

謝謝,我會給它一個鏡頭。我會告訴你! – cocheese

+0

試了一下,它的工作原理。第一個解決方案中的小錯誤。我需要將變量文件名放在括號中。否則,它會給出錯誤。通過這種方式,它得到適當的級聯 'awk '/config.vm.define [[:space:]] \「[az] * \」[[:space:]] do [[:space:]] \ | [a-zA-Z _] * \ |/{f = 1; i ++} f {print $ 0>(「block」i)} /end/{f = 0}'Vagrantfile' – cocheese

+0

太棒了!感謝評論:) –