2016-11-24 52 views
2

我想將我的shell腳本轉換爲使用datadriven方法。但是由於在任何shell中都沒有「表格」類型的值(我知道),有什麼建議替代方法來做到這一點?Datadriven shell編程?建議,請

我正在尋找的是解決方案,將允許人們做這樣的事情:

animals = [['horse', 300 'brown'], 
      ['cat', 3, 'black'], 
      ['elephant', 3000, 'grey'], 
      ['mouse', 0.3, 'grey']] 
for a in animals ; do 
    echo "A typical $a[1] is $a[3] and weighs about $a[2] kilograms." 
done 

更確切地說,我想嘗試一些命令,看看其中的一個是可用的,然後發送參數:

commands = [['c1', '-m', '-i'], 
      ['c2', '-message', '-icon'], 
      ['c3', '/m', '/i']] 
for c in commands ; do 
    if exists c[1] ; then 
    command = c[1] 
    message_option = c[2] 
    icon_option = c[3] 
    break; 
    fi 
done 
$command $message_option "message" $icon_option icon 
+0

爲什麼不把你的'表'數據放到一個文件中,然後用'awk'或類似的程序讀取它呢? – VM17

+0

你正在使用哪個外殼? 'bash','ksh'或'zsh'? – Inian

+0

我正在考慮'python',但是因爲可移植性問題而決定不使用它。所以我的做法是'bash'。該腳本需要做很多其他的事情,但是探索與'awk'結合會很有趣,因爲它也可以「隨處可見」。那麼一個shell腳本如何調用'awk'來做這個例子(我將更新它以更精確地指出我需要做什麼)? – thoni56

回答

4

沒有bashisms需要。

#!/bin/sh 
while read animal weigth colour; do 
    printf '%s\n' "A typical $animal is $colour and weighs about $weight kilos." 
done << EOF 
horse 300 brown 
cat 3 black 
elephant 3000 grey 
mouse 0.3 grey 
EOF 

觀察如何按名稱引用的元素與1,不神祕的索引,2,3,它不叉:這可以用這裏文檔while read循環中讀取被幹淨利落地解決了/ exec任何外部命令並擊敗另一個答案中看到的循環體中的3個awk。

+2

@Inian和Jens是非常令人迷惑笑 – 2016-11-24 10:46:20

+2

@Mayerz而且我們不是唯一的:-) – Jens

+0

@Jens:提供了使用只是因爲OP的帖子看起來類似陣列的方法。 – Inian

0

試試這個嗎?

cat file 
'horse', 300, 'brown' 
'cat', 3, 'black' 
'elephant', 3000, 'grey' 
'mouse', 0.3, 'grey' 

for i in {1..4} ; 
do 
    animal=$(awk -F, -v var="$i" 'NR== var {print $1}' file) 
    weight=$(awk -F, -v var="$i" 'NR== var {print $2}' file) 
    colour=$(awk -F, -v var="$i" 'NR== var {print $3}' file) 
    echo "A typical "$animal" is "$colour" and weighs about "$weight" kilos." 
done 

輸出 -

A typical 'horse' is 'brown' and weighs about 300 kilos. 
A typical 'cat' is 'black' and weighs about 3 kilos. 
A typical 'elephant' is 'grey' and weighs about 3000 kilos. 
A typical 'mouse' is 'grey' and weighs about 0.3 kilos. 
+0

這是CPU週期的浪費。它分叉12個進程並讀取同一文件12次。 – Jens

+0

表現不是要求之一,但在某些情況下這可能是有效的觀察。 – thoni56

2

您可以定義和bash使用associative-arrays您的需求。

#!/bin/bash 

# declaring the Associative array 
declare -a animals 

animals[0]="'horse':300:'brown'" 
animals[1]="'cat':3:'black'" 
animals[2]="'elephant':3000:'grey'" 
animals[3]="'mouse':0.3:'grey'" 

for animal in "${animals[@]}" 
do 
    myArray=(${animal//:/ }) 
    printf "A typical "${myArray[0]}" is "${myArray[2]}" and weighs about "${myArray[1]}" kilograms.\n" 
done 

在上述唯一棘手的部分是類型的parameter-expansion

${parameter/pattern/string} 
      The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. 
If pattern begins with ‘/’, all matches of pattern are replaced with string. Normally only the first match is replaced. 

所以理想的是串'horse':300:'brown'被分割爲各個元件和存儲其隨後用於訪問各個元件陣列myArray在一個C風格的循環。

+0

很明顯,我不知道陣列中的'bash' ... Duh ... – thoni56

+0

@ thoni56:我以爲你需要一個使用你的例子中的數組的方法!但現在未被接受? :( – Inian

+1

我並沒有特別要求如何實現數組,而是數據驅動的shell腳本。我接受了你的答案,因爲它當時絕對是最好的答案,而且我仍然投票贊成你給我講解bash數組,但@Jens的回答對我的實際問題來說是一個更好的解決方案。考慮接受他的回答是一個信號,他對我想達到的目標的理解甚至比你的更好。 – thoni56