Приветствую. Я не уверен что верно обозначил тему, ну думаю меня поправят если что.
По работе мне часто приходится писать скрипты на bash дергающие различные данные (как правило это ip шники и имена хостов) из mysql, и делающие из этих данных массив.
И вот подумалось зачем все время писать одно и тоже не лучше ли сделать одну функцию к которой всегда потом обращаться.
и сделал
________________________________________________________________________
allip=`echo "select \\\`ip\\\` from \\\`servers\\\` order by \\\`serverid\\\` ;" | mysql -uroot -p*** -B namedb | sed s'/ip//'p`
таким образом я присвоил $allip список ip разделенных пробелам
sumip=`echo ${allip}| wc -w`
Узнал сколько ip шников у меня в переменой $allip
createmas () {
loop=1
until [ "$loop" -gt "$1" ]
do
$2[$loop]=`echo $3 |cut -d ' ' -f"$loop"`
let loop++
done
}
createmas "${sumpolip}" ipaddress "${allip}"
__________________________________________________________
Запускаю
/home/soln/test: строка 18: ipaddress[1]=192.168.0.10: команда не найдена
/home/soln/test: строка 18: ipaddress[2]=10.0.10.8: команда не найдена
и тд
при этом если скопировать " ipaddress[5]=10.0.10.8" в консоль или в таком виде положить в скрипт то массив создается.
Опытным путем выяснил, что если в имени массива $2[$loop], $2 заменить на скажем n массив создается, то есть bash не понимает переменную в имени массива
Можно ли как нибудь заставит bash воспринимать позиционную переменную в имени массива?
Ps гуглил безрезультатно, эксперементы типа `echo $2`[$loop]=... тоже не помогли
Bash: Имя массива, пристраиваемое через позиционую переменую
[console]alexander@goblin ~ $ export ARR_NAME=MY_ARR
alexander@goblin ~ $ declare $ARR_NAME[2]=1
alexander@goblin ~ $ echo ${MY_ARR[2]}
1
[/console]
хорошо?
хорошо?
Прежде всего спасибо за ответ.
Увы нет. Ругаться в этом случае скрипт перестает и даже внутри цикла создает массив, но не передает его родителю. Что странно так как если ручками рядом объявить массив (test[1]=test)то родителю он передается, если же попытается его экспортировать то происходит что то вообще мне непонятное
Привожу пример скрипта
#!/bin/bash
allip='92.168.0.10 10.0.10.5'
allname='name name1'
sumpolip=`echo ${allip}| wc -w`
sumname=`echo ${allname}|wc -w`
loop=1
creeatmas () {
loop=1
until [ "$loop" -gt "$1" ]
do
declare -a $2[$loop]=`echo $3 |cut -d ' ' -f"$loop"`
echo \$\{ipaddress\[\$loop\]\} "${ipaddress[$loop]}" \$\{name\[\$loop\]\} "${name[$loop]}"
let loop++
done
}
creeatmas "${sumpolip}" ipaddress "${allip}"
creeatmas "${sumname}" name "${allname}"
echo \$\{ipaddress\[\*\]\} "${ipaddress[*]}" \$\{name\[\*\]\} "${name[*]}"
#!/bin/bash
allip=( 92.168.0.10 10.0.10.5 )
allname=( name0 name1 )
i=0
until [ ${i} -eq ${#allip[@]} ]; do
echo map-ip-to-name ${allip[$i]} ${allname[$i]}
let i++
done
exit
проблемы скорее всего возникают из-за области видимости - функция это подпроцесс.
чтобы не морочиться с определением заранее, можно использовать функциональный стиль:
#!/bin/bash
allip='92.168.0.10 10.0.10.5'
allname='name0 name1'
sumpolip=`echo ${allip}| wc -w`
sumname=`echo ${allname}|wc -w`
loop=0
# немного переделаем функцию, чтобы она выводила результат через echo.
# выводит она строки вида [0]=значение. так тоже можно определять массивы - Arr=([0]=foo [1]=bar)
# $1 = count
# $2 = list of values
creatmas () {
loop=0
until [ "$loop" -eq "$1" ]
do
i=$(( loop + 1 ))
echo "[$loop]=`echo $2 |cut -d ' ' -f"$i"`"
let loop++
done
}
# построим вывод для данных allip
V=`creatmas $sumpolip "${allip}"`
# и определим из них массив с нужным именем в локальном скоупе.
declare -a array_ips=( ${V} )
# и для второго массива
V=`creatmas $sumpolip "${allname}"`
declare -a array_names=( ${V} )
# PROFIT!
echo ${array_names[0]} ${array_ips[0]}
просто export вместо declare используйте...
Извините за молчание, завалили работой.
Прежде всего спасибо за внимание. )
просто export вместо declare используйте...
Пробовал не помогло. И да, недавно прочитал что export передает данные дочерним процессам и не может вернуть родителю. Поправьте если не прав.
aannnuuu
Спасибо это работает только я не понял зачем вы вели i. Ну в общем в результате получилось следующие
#!/bin/bash
allip='92.168.0.10 10.0.10.5 195.54.192.33'
allname='name0 name1 name2'
sumpolip=`echo ${allip}| wc -w`
sumname=`echo ${allname}|wc -w`
loop=0
# немного переделаем функцию, чтобы она выводила результат через echo.
# выводит она строки вида [0]=значение. так тоже можно определять массивы - Arr=([0]=foo [1]=bar)
# $1 = count
# $2 = list of values
creatmas () {
loop=0
until [ "$loop" -ge "$1" ]
do
let loop++
echo "[$loop]=`echo $2 |cut -d ' ' -f"$loop"`"
done
}
# построим вывод для данных allip
V=`creatmas $sumpolip "${allip}"`
# и определим из них массив с нужным именем в локальном скоупе.
declare -a array_ips=( ${V} )
# и для второго массива
V=`creatmas $sumpolip "${allname}"`
declare -a array_names=( ${V} )
# PROFIT!
#creatmas $sumpolip "${allip}"
mas () {
loop=0
until [ "$loop" -ge "${#array_names[@]}" ]
do
echo \$\{array_names\[$loop\]\} ${array_names[$loop]} ${array_ips[$loop]} \$\{array_ips\[$loop\]\}
let loop++
done
}
mas
Если из скрипта запускать другой командой source, то переменные, определённые
в другом, останутся в запускающем, см. описание source в "man bash".
Пётр.