
Я пытаюсь написать bash-скрипт, который автоматически считывает все имена файлов в текущем и пользовательских каталогах, затем применяет имена новых созданных образов Docker к найденным файлам yml через kubectl, а затем считывает из двух массивов имена образов и полные имена реестра:
declare -a IMG_ARRAY=`docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | sed ':a;N;$!ba;s/\n/ /g'`
declare -a IMG_NAME=`docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | awk -F'/' '{print $3}' | cut -f1 -d"." | sed ':a;N;$!ba;s/\n/ /g'`
IFS=' ' read -r -a array <<< "$IMG_NAME"
for element in "${array[@]}"
do
kubectl set image deployment/$IMG_NAME $IMG_NAME=$IMG_ARRAY --record
kubectl rollout status deployment/$IMG_NAME
done
Оба массива имеют одинаковое количество индексов. Мой цикл должен брать первые индексы из IMG_NAME и помещать в команды kubectl для каждого индекса массива. Сейчас он берет весь массив...
решение1
declare -a IMG_ARRAY=`...`
Это не создает много массива, весь вывод от подстановки команды назначается нулевому элементу массива. Фактический синтаксис назначения массива — , т.е. со скобками и элементами как отдельными словами.name=(elem1 elem2 ... )
Вы можете использовать разбиение по словам, чтобы разделить вывод на элементы, но это все равно потребует скобок, и вы будете подвержены IFS
и подстановке. declare -a aaa=( $(echo foo bar) )
создает два элемента foo
и bar
. Обратите внимание, что он разделяет по пробелу между словами, а не только по новым строкам.
Использование mapfile
/ readarray
здесь, вероятно, лучше, поскольку оно явно сделано для чтения строк в массив. Текст справки командной строки ( help mapfile
) описывает это:
mapfile: mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
Read lines from the standard input into an indexed array variable.
Read lines from the standard input into the indexed array variable ARRAY, or
from file descriptor FD if the -u option is supplied. The variable MAPFILE
is the default ARRAY.
решение2
Насколько я понимаю, вы хотите получить обработанные выходные данные docker images
в виде двух массивов, где каждый элемент массива соответствует строке обработанных выходных данных.
Этот скрипт не тестировался, поскольку я не знаю ни вывода, docker images
ни синтаксиса команды для kubectl
.
mapfile -t IMG_ARRAY < <(docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | sed ':a;N;$!ba;s/\n/ /g')
mapfile -t IMG_NAME < <(docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | awk -F'/' '{print $3}' | cut -f1 -d"." | sed ':a;N;$!ba;s/\n/ /g')
total=${#IMG_NAME[*]}
for (( i=0; i<$(( $total )); i++ ))
do
kubectl set image deployment/$IMG_NAME[$i] $IMG_NAME[$i]=$IMG_ARRAY[$i] --record
kubectl rollout status deployment/$IMG_NAME[i]
done
Видетьhttps://www.cyberciti.biz/faq/bash-iterate-array/иhttps://mywiki.wooledge.org/BashFAQ/005для объяснений.
Вместо
total=${#IMG_NAME[*]}
for (( i=0; i<$(( $total )); i++ ))
Вы также можете использовать
for i in ${!IMG_NAME[@]}
видетьhttps://stackoverflow.com/questions/6723426/цикл-по-массивам-печать-обоих-индексов-и-значений