#bash #shell #for-loop
#bash #оболочка #for-цикл
Вопрос:
Я пишу скрипт bash, приведенный ниже (пожалуйста, игнорируйте имена переменных с заглавными буквами, это всего лишь мой тестовый файл):
#!/bin/bash
create_nodes_directories(){
HOSTS=(192.168.110.165 192.168.110.166 192.168.110.167)
accounts=('accountnum11' 'accountnum12' 'accountnum13')
for i in "${!HOSTS[@]}"; do
read -r curhost _ < <(hostname -I)
printf 'Enter the key pair for the %s noden' "${accounts[i]}"
printf "Enter public keyn"
read -r EOS_PUB_KEY
printf "Enter private keyn"
read -r EOS_PRIV_KEY
PRODUCER=${accounts[i]}
args=()
args =("$curhost")
for j in "${!HOSTS[@]}"; do
if [[ "$i" != "$j" ]]; then
args =("${HOSTS[$j]}")
else
continue;
fi
done
#echo 'Array before test:'"${args[*]}"
create_genesis_start_file "$EOS_PUB_KEY" "$EOS_PRIV_KEY" "${HOSTS[$i]}" "$PRODUCER" args
create_start_file "$EOS_PUB_KEY" "$EOS_PRIV_KEY" "${HOSTS[$i]}" "$PRODUCER" args
done
}
create_genesis_start_file(){
EOS_PUB_KEY=$1
EOS_PRIV_KEY=$2
CURRENTHOST=$3
PRODUCER=$4
peerags="$5[@]"
peers=("${!peerags}")
echo 'Genesis Currenthost is:'"$CURRENTHOST"
#echo "${peers[*]}"
VAR=""
length=${#peers[@]}
last=$((length - 1))
for i in "${!peers[@]}" ; do
if [[ "$i" == "$last" ]]; then
VAR ="--p2p-peer-address ${peers[$i]}:8888 \"
else
VAR =$"--p2p-peer-address ${peers[$i]}:8888 \"$'nt'
fi
done
}
create_start_file(){
EOS_PUB_KEY=$1
EOS_PRIV_KEY=$2
CURRENTHOST=$3
PRODUCER=$4
peerags="$5[@]"
peers=("${!peerags}")
echo 'Start file Currenthost is:'"$CURRENTHOST"
#echo "${peers[*]}"
}
create_nodes_directories
Для каждой итерации первого цикла for я показываю третий аргумент $CURRENTHOST
, который передается функциям create_genesis_start_file
и create_start_file
.
Для первой итерации вывод:
Genesis Currenthost is:192.168.110.165
Start file Currenthost is:192.168.110.167
Вторая итерация:
Genesis Currenthost is:192.168.110.166
Start file Currenthost is:192.168.110.167
Третья итерация,
Genesis Currenthost is:192.168.110.167
Start file Currenthost is:192.168.110.167
Genesis Currenthost
соответствует ожиданиям и Start file Currenthost
должно быть таким же с ним. Я не понимаю, почему Start file Currenthost
всегда устанавливается как 192.168.110.167
.
Если я удалю приведенный ниже код, create_genesis_start_file
он будет работать нормально:
VAR=""
length=${#peers[@]}
last=$((length - 1))
for i in "${!peers[@]}" ; do
if [[ "$i" == "$last" ]]; then
VAR ="--p2p-peer-address ${peers[$i]}:8888 \"
else
VAR =$"--p2p-peer-address ${peers[$i]}:8888 \"$'nt'
fi
done
Я не понимаю точной проблемы, почему изменяется значение переменной? Пожалуйста, помогите.
Комментарии:
1. Вы используете переменную
i
как в основномfor i in "${!HOSTS[@]}"
цикле, так и вcreate_genesis_start_file
функции, и функция частично изменяет значение в цикле. Чтобы избежать конфликта, либо используйте разные имена переменных в двух местах, либо объявите ихlocal
в функции (или оба).2. о да, моя ошибка! Спасибо. Проблема решена.
Ответ №1:
Для "$5[@]"
меня это выглядит странно. Вы не можете использовать скаляр $5
, как если бы это был массив.
Кажется, вы хотите передать весь массив в качестве параметра. Поскольку у bash нет собственного способа сделать это, я предлагаю, чтобы на вызывающей стороне вы передавали "${args[@]}"
в качестве параметра, а внутри вашей функции вы выполняли
shift 4
peers=( "$@" )
Другая возможность, которая, однако, нарушает идею инкапсуляции, заключается в том, чтобы использовать treet peers
как глобальную переменную, доступную для всех функций. При таком подходе вы бы на стороне вызывающей стороны собирали информацию, уже находящуюся в переменной peers
, вместо args
.
Из стиля программирования глобальные переменные (пересекающие границы функций) обычно не нравятся по уважительным причинам, но, по моему личному мнению, если вы просто выполняете простые сценарии оболочки, я бы счел это приемлемым решением.