Datadriven программирование оболочки? Предложения, пожалуйста

Я хотел бы преобразовать свой сценарий оболочки, чтобы использовать подход, основанный на данных. Но поскольку в какой-либо оболочке (из известных мне) значений типа "таблицы" нет, каковы возможные альтернативные способы сделать это?

То, что я ищу, это решения, которые позволили бы делать такие вещи, как:

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

3 ответа

Решение

Нет необходимости в bashisms. Это может быть аккуратно решено с помощью документа, прочитанного while read цикл:

#!/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. Он не запускает / не выполняет никаких внешних команд и бьет 3 awk в теле цикла, как показано в другом ответе.

Вы можете определить и использовать ассоциативные массивы в bash по вашему требованию.

#!/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/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.

Try this?

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.
Другие вопросы по тегам