LinuxForum.Fans
Тема

Bash: Имя массива, пристраиваемое через позиционую переменую

Автор: soln 8 сообщений 1974 просмотров
#196855

Приветствую. Я не уверен что верно обозначил тему, ну думаю меня поправят если что.
По работе мне часто приходится писать скрипты на 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]=... тоже не помогли

#196929

[console]alexander@goblin ~ $ export ARR_NAME=MY_ARR
alexander@goblin ~ $ declare $ARR_NAME[2]=1
alexander@goblin ~ $ echo ${MY_ARR[2]}
1
[/console]
хорошо?

#196990
Fat-Zer написал:

хорошо?

Прежде всего спасибо за ответ.

Увы нет. Ругаться в этом случае скрипт перестает и даже внутри цикла создает массив, но не передает его родителю. Что странно так как если ручками рядом объявить массив (test[1]=test)то родителю он передается, если же попытается его экспортировать то происходит что то вообще мне непонятное

Привожу пример скрипта

text

#!/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[*]}"

#197016

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

#197018

проблемы скорее всего возникают из-за области видимости - функция это подпроцесс.
чтобы не морочиться с определением заранее, можно использовать функциональный стиль:

#!/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]}

#197040

просто export вместо declare используйте...

#198722

Извините за молчание, завалили работой.
Прежде всего спасибо за внимание. )

Fat-Zer написал:
просто export вместо declare используйте...

Пробовал не помогло. И да, недавно прочитал что export передает данные дочерним процессам и не может вернуть родителю. Поправьте если не прав.

aannnuuu
Спасибо это работает только я не понял зачем вы вели i. Ну в общем в результате получилось следующие

text

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

#198770

Если из скрипта запускать другой командой source, то переменные, определённые
в другом, останутся в запускающем, см. описание source в "man bash".

Пётр.

Войдите или зарегистрируйтесь, чтобы ответить.