Перебор массива и выполнение команды, хранящейся в переменных

#bash #unix

#bash #unix

Вопрос:

Я пытаюсь скомпилировать большой проект, который включает в себя переход в разные каталоги и компиляцию там. У меня есть три массива, все они содержат команды, первый массив содержит обход каталога, второй массив содержит команды компиляции, а третий массив содержит сообщения об ошибках.

Я настроил свои массивы следующим образом

 task[0]="cd vssl/make/; make clean;"
compile[0]="make all"
error[0]="echo "We failed at vssl install""

task[1]="cd ../../web/make/; make clean;"
compile[1]="make install"
error[1]="echo "We failed at web install""
  

Теперь мне нужен цикл for, который будет работать следующим образом

 for i in {0..$size_of_array}
do
    eval ${task[$i]}
    if (eval ${compile[$i]}); then
        echo "Done"
    else
        eval ${error[$i]}
        break
    fi
done
  

Я много чего перепробовал и не уверен, как этого добиться. for i in "${task[@]}" у меня тоже не работает, потому что у меня есть три переменные. У кого-нибудь есть представление о том, как это обойти?

Спасибо всем, кто может помочь. 🙂

Ответ №1:

Размер task массива ${#task[@]} (прекрасный синтаксис, не так ли?). Таким образом, вы можете начать свой цикл как

 for ((i=0; i<${#task[@]};   i))
  

Смотрите for команду и раздел об АРИФМЕТИЧЕСКОМ ВЫЧИСЛЕНИИ в bash(1) для получения подробной информации.

Комментарии:

1. Большое вам спасибо, это именно то, что я хотел!!! Тоже отлично работает. Спасибо!

2. Отличная идея! Все это объясняется в разделе «Расширение параметров» bash(1).

Ответ №2:

Вы можете вычислять $i по ходу работы:

 i=0
for cmd in "${task[@]}"; do
  eval $cmd
  if (eval ${compile[$i]}); then
    echo "Done"
  else
    eval ${error[$i]}
    break
  fi
  i=`expr $i   1`
done
  

Комментарии:

1. Я боялся, что вы скажете это, потому что я хотел, чтобы красивый цикл for делал мои вещи за меня. Но большое вам спасибо, это сработало довольно хорошо.

2. Ответ @AndrewSchulman тоже выглядит хорошо; Признаюсь, я не знал, что вы могли бы написать for-циклы, подобные тем, что в bash.

Ответ №3:

Почему в мире у вас есть три массива? Оболочка не так хороша для программирования, но она отлично подходит для выполнения команд, что вы, похоже, и делаете здесь. Итак, просто сделайте это:

 set -ex
make -C vssl/make clean all
make -C ../../web/make/ clean install
...
  

Недостаточно причудливо? ОК:

 die() { echo "$*" >amp;2; exit 1; }
run() { "$@" || die "Failed (exit $?) at $*"; }
run make -C vssl/make clean all
run make -C ../../web/make/ clean install