2016-02-24 3 views
2

Так что я пытаюсь что-то сделать, не уверен, что это возможно. У меня есть следующий код:Назначение динамических имен переменных bash с использованием цикла for

for i in {0..5}; do 
    if [[ -f ./user$i ]]; then 
     group$i=$(grep -w "group" ./user0|awk '{print $2}'|perl -lape 's/\s+//sg') 

То, что я хочу сделать, это присвоить уникальный переменную для каждого экземпляра {0..5} так group1 GROUP2 group3 Group4 для каждого имени переменной. Затем я изменил бы ./user0 на ./user$i и создаю динамический список переменных, основанный на моей последовательности. Возможно ли это? Я получаю следующую ошибку при попытке выполнить это, и я не уверен, что я действительно сделал, что bash не нравится.

test.sh: строка 16: group0 = J: команда не найдена

+2

Я рекомендую использовать Баш массивы вместо динамических имен переменных, если это возможно. –

+0

@KurtStutsman - Я тоже думал, что – Soren

ответ

4

Kurt Stutsman обеспечивает правильный указатель в комментарии на вопрос: использование Bash массивы, чтобы решить вашу проблему.

Вот упрощенный пример:

groups=() # declare an empty array; same as: declare -a groups 
for i in {0..5}; do 
    groups[i]="group $i" # dynamically create element with index $i 
done 

# Print the resulting array's elements. 
printf '%s\n' "${groups[@]}" 

см в нижней части этого ответа для других способов перечислить элементы массива ${groups[@]}.

  • bash массивы могут быть динамически расширены (и может быть даже редкие - индексы элементов не должны быть смежными)

    • Следовательно, простое присваивание элементу $i работ, без предварительного проклейки из массив.
  • Обратите внимание, как $i нужно не быть с префиксом $ в индексе массива, потому что индексы массивов оцениваются в арифметическом контексте (тот же контекст, в котором оценивается $((...)) выражения).


Что касается , что вы сделали неправильно:

group$i=... 

не признается в качестве переменной уступки Bash, потому что - принято буквально - group$i не является допустимым идентификатором (имя переменной).

Потому что это не так, Bash продолжает анализировать до следующего метасимволом оболочки не найден, а затем интерпретирует полученное слово как команды для выполнения, в вашем случае в результате сообщения об ошибке group0=j: command not found.


Если по какой-то причине, вы не хотите использовать массив, чтобы полностью избежать этой проблемы, вы можете работы вокруг проблемы:

Привлекая переменный-декларирование встроенной [команда], такие как declare, local или export, вы вынуждаете Bash выполнить РАЗЛОЖЕНИЯ первого, который расширяет group$i к действительному против перед тем, как передать его встроенному.

  • user2683246's answer демонстрирует следующий лучший подход с использованием declare (или, если локальные переменные внутри функции желательны, local) для создания переменных.

  • Soren's answer использует export, но это только целесообразно, если вы хотите создать среды переменные видимых в дочерние процессы а не просто оболочка переменных.

Caveat: С помощью этой техники, обязательно двойные кавычки РИТ для того, чтобы захватить полную стоимость; для иллюстрации:

i=0; declare v$i=$(echo 'hi, there'); echo "$v0" # !! WRONG -> 'hi,': only UP TO 1ST SPACE 

i=0; declare v$i="$(echo 'hi, there')"; echo "$v0" # OK -> 'hi, there' 

Других способов перечислить groups массив, созданный выше:

# Enumerate array elements directly. 
for element in "${groups[@]}"; do 
    echo "$element" 
done 

# Enumerate array elements by index. 
for ((i = 0; i < ${#groups[@]}; i++)); do 
    echo "#$i: ${groups[i]}" 
done 
+0

Хорошо, что имеет смысл. Но мне трудно понять, как назначить значения другим моим переменным, которые я изложил выше. Я понимаю, как работает ваш пример, но как применить это к моей группе = $ (command) синтаксис – stobiewankenobi

+0

О nvmnd Я получил его работу. Я не совсем понимаю, почему это работает. group [i] = "group $ i" group [i] = $ (grep -w "group" ./ user $ i | awk '{print $ 2}' | perl -lape 's/\ s + // sg') – stobiewankenobi

+0

Так что это работает, но как насчет остальной части моей проблемы, как описано выше? Как написать каждое значение для файл и иметь его уникальным? Мой оператор Echo не работает при попытке этого с помощью $ {group [@]}. Очевидно, если я изменю его на [1], он будет работать, но как это сделать для каждой переменной динамически? – stobiewankenobi

1

Попробуйте использовать экспорт или объявить функцию как этот

for i in {0..5}; do 
    if [[ -f ./user$i ]]; then 
     export group$i=$(grep -w "group" ...... 

с заявляют

for i in {0..5}; do 
    if [[ -f ./user$i ]]; then 
     declare group$i=$(grep -w "group" ...... 

где export делает значение доступным для подпроцессов и declare, доступный только в том же скрипте.

+0

О, человек. ИДЕАЛЬНО. Работал 100%. Вы не возражаете, объясняя мне, ПОЧЕМУ это сработало? Я читаю команду экспорта, но я не совсем понимаю, почему это работает. – stobiewankenobi

+0

Обновленный мой код выше с другим вопросом для вас. Это работает, но я столкнулся с другой проблемой. – stobiewankenobi

+0

Вы должны задать новый вопрос, а не обновлять – Soren

4

Использование declare group$i=... вместо просто group$i=...

Смежные вопросы