LINUX.ORG.RU
ФорумAdmin

вопрос по переменным в скрипте bash

 


1

3

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

kof=1
per_$kof

Как такой переменной присвоить значение, на такое присвоение выдаёт ошибку:

per_$kof=22

★★

Ответ на: комментарий от v4567

Как ты и хочешь, строке присваивается значение.

anonymous
()

BTW, если есть возможность, просто возьми tcl вместо bash - там и с подстановками проще намного

Deleted
()
declare per_$kof=22
anonymous
()
Ответ на: комментарий от anonymous

Не пойму как при помощи eval можно сделать то что мне нужно.

У меня в процессе работы скрипта переменная должна менять своё название, например:

per_1
per_2
per_3
....
То есть слово per_ остаётся постоянным, а меняется только коэффициент - 1, 2, 3 и т. д. Сколько будет коэффициентов и какие я заранее не знаю, это получится в процессе работы скрипта и в эти переменные мне надо будет записывать значения. Как такое можно сделать и можно ли вообще так сделать?

v4567 ★★
() автор топика
Ответ на: комментарий от v4567

BTW, если есть возможность, просто возьми tcl вместо bash - там и с подстановками проще намного

нужен именно bash

v4567 ★★
() автор топика

Как такой переменной присвоить значение

Подобное построение в sh неудобно от слова «совсем». Ты с ним замучаешься только. Удобным в данном случае будет содержать в одной переменной сразу несколько значений и использовать их по необходимости.

Deleted
()
Ответ на: комментарий от v4567

Как ты собираешься это использовать и почему не подходит ассоциативный массив?

anonymous
()
Ответ на: комментарий от v4567

Это просто проклятие bash какое-то, я только что в соседнем топике предсказывал, что из всех решений ты выберешь худшее и вот ты уже тут из всех правильных вариантов зачем-то ухватился за eval. Ты им отдавишь себе пальцы! Не трогай eval!

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Баш, плохой дизайн и шиза идут рука об руку.

anonymous
()
Ответ на: комментарий от legolegs

Огромное всем спасибо за помощь!

Заработали 3 варианта, eval и declare в том числе.

Вариант номер 1 без eval и declare:

#!/bin/bash

kof=1

(( per_kof=0 ))


for ((kof=1; kof<=10 ; kof++))
 do
   (( per_kof+=1 ))
   echo "per_$kof: $per_$kof"
done

Вариант номер 2 с eval:

#!/bin/bash

kof=1

eval  per_$kof=0


for ((kof=1; kof<=10 ; kof++))
 do
   (( per_kof+=1 ))
   echo "per_$kof: $per_$kof"
done

Вариант номер 3 с declare:

#!/bin/bash

kof=1

declare  per_$kof=0


for ((kof=1; kof<=10 ; kof++))
 do
   (( per_kof+=1 ))
   echo "per_$kof: $per_$kof"
done

v4567 ★★
() автор топика
Ответ на: комментарий от Deleted

;)

Зачем сказал? :) Ты ещё отметь, что когда ТС реализует свою «хотелку» у него в скрипте будет не одна per_N, а все per_1, per_2, ... per_N-1, per_N

anymouze ★★
()
Ответ на: ;) от anymouze

Ты в курсе, что у тебя в цикле всего одна переменная: ${per_kof}?

Да в курсе. Это просто скрипт для проверки.

v4567 ★★
() автор топика
Ответ на: ;) от anymouze

Зачем сказал?

Так вижу откровенный тупизм, а посмотреть на результат и увидеть, что вывод совсем не тот, который задан в задаче, ума не хватает.

Deleted
()
Ответ на: комментарий от Deleted

Так вижу откровенный тупизм, а посмотреть на результат и увидеть, что вывод совсем не тот, который задан в задаче, ума не хватает.

Ну почему же, именно тот который и задан в задаче. название переменной per_.... меняется и каждая новая переменная получает своё значение.

v4567 ★★
() автор топика
Ответ на: комментарий от v4567

название переменной per_.... меняется и каждая новая переменная получает своё значение.

Ты хочешь заверить меня, что ты получил 10 единиц?

Deleted
()
Ответ на: комментарий от Deleted

Ты хочешь заверить меня, что ты получил 10 единиц?

Вот какой результат во всех трёх вариантах:

per_1: 1
per_2: 2
per_3: 3
per_4: 4
per_5: 5
per_6: 6
per_7: 7
per_8: 8
per_9: 9
per_10: 10

Не веришь, возьми и проверь.

v4567 ★★
() автор топика
Ответ на: комментарий от v4567

Не веришь, возьми и проверь.

Так я проверил. В этом то и дело. Ты уверен, что это именно тот результат, который ты задумывал? А я вот вижу вместо 10 единиц, одну переменную, значение которой увеличивается с каждым шагом цикла на единицу.

Deleted
()
Ответ на: комментарий от Deleted

Где же одна переменная, их 10. per_1, per_2 и т.д. и у каждой своё значение, да это значение увеличивается на единицу, как и коэффициент в названии переменной.

v4567 ★★
() автор топика
Ответ на: комментарий от v4567

Хинт: выполни следующую команду

kof=10 && echo $per_$kof
Подумай. Сделай
echo $per_
Прозрей.

gremlin_the_red ★★★★★
()
Ответ на: комментарий от v4567

Я уже приводил, вот он:

Ты под дурочка не коси. Это результат счётчика в цикле. А теперь сделай вывод после цикла.

Deleted
()
Ответ на: комментарий от Deleted

По моему это ты косишь под дурочка и это тебе подтвердят форумчане которые читают этот пост.
Вывод какой именно переменной после цикла тебе нужен?

v4567 ★★
() автор топика
Ответ на: комментарий от v4567

Ла у тебя все переменные per_N пустые будут. Ещё раз, $per_$kof — это ${per_}${kof}, а не то, что ты там подумал

gremlin_the_red ★★★★★
()
Ответ на: комментарий от v4567

Вот на это что-нибудь возрази (после выполнения)

#!/bin/bash
a=''
# Явные присвоения от меня :)
_per_1=1 # явно создаю переменную, присваиваю значение
_per_2=2 # явно создаю следующую переменную, присваиваю значение
_per_3=3 # явно создаю следующую переменную, присваиваю значение

k=1 # коэффициент имени
echo $((_per_$k)) # смотрим, что в переменной
k=2 # переходим к следующей переменной 
echo $((_per_$k)) # смотрим, что в переменной
k=3
echo $((_per_$k)) # смотрим, что в переменной
k=4 # этой переменной ещё не существует
echo $((_per_$k)) # смотрим, что в переменной

echo 'press any key to continie...'
read a

echo 'variant 1 by ТС'

kof=1

(( per_kof=0 ))


for ((kof=1; kof<=10 ; kof++))
 do
   (( per_kof+=1 ))
   echo "per_$kof: $per_$kof"
done

echo
echo 'stupid verify by anymouze'
echo $per_1
echo $per_2
echo $per_3
echo $per_4
echo $per_5
echo $per_6
echo $per_7
echo $per_8
echo $per_9
echo $per_10
echo 'press any key to continie...'
read a

echo 'variant 2 by ТС'

kof=1

eval  per_$kof=0


for ((kof=1; kof<=10 ; kof++))
 do
   (( per_kof+=1 ))
   echo "per_$kof: $per_$kof"
done

echo
echo 'stupid verify by anymouze'
echo $per_1
echo $per_2
echo $per_3
echo $per_4
echo $per_5
echo $per_6
echo $per_7
echo $per_8
echo $per_9
echo $per_10
echo 'press any key to continie...'
read a

echo 'variant 3 by ТС'

kof=1

declare  per_$kof=0


for ((kof=1; kof<=10 ; kof++))
 do
   (( per_kof+=1 ))
   echo "per_$kof: $per_$kof"
done

echo
echo 'stupid verify by anymouze'
echo $per_1
echo $per_2
echo $per_3
echo $per_4
echo $per_5
echo $per_6
echo $per_7
echo $per_8
echo $per_9
echo $per_10

anymouze ★★
()
Ответ на: комментарий от v4567

Вывод какой именно переменной после цикла тебе нужен?

Все с тобой понятно. Под дурочка косим. Но я не поленился и вставил в твой скрипт строки: коментарий: zvezdochiot (14 апр. 2019 г., 17:44:07)

И получил следующее:

per_1: 1
per_2: 2
per_3: 3
per_4: 4
per_5: 5
per_6: 6
per_7: 7
per_8: 8
per_9: 9
per_10: 10



------
10

Deleted
()
Ответ на: комментарий от v4567

Вот это похоже на то, что ты желаешь (но я не уверен, что там нет сюрпризов)

#!/bin/bash
a=''

kof=1

eval  per_$kof=0

for ((kof=1; kof<=10 ; kof++))
 do
   eval per_$kof=$kof
   echo "per_$kof: $per_$kof"
done

echo 'stupid verify by anymouze'
echo $per_1
echo $per_2
echo $per_3
echo $per_4
echo $per_5
echo $per_6
echo $per_7
echo $per_8
echo $per_9
echo $per_10
echo 'press any key to continie...'
read a

anymouze ★★
()
Ответ на: комментарий от anymouze

echo «per_$kof: $per_$kof»

Всё равно не то выводит:

echo "${per_}${kof}"

Так читается что выводит: «пустышку» + счётчик.

Deleted
()

Какой же хренью занимаются в этом треде. Родина дала тебе массивы, структурируй данные - не хочу, хочу жрать eval!

Сейчас ещё кто-нибудь читнёт в мане про indirect expansion и nameref и родит ещё более бессмысленные и беспощадные простыни кода и тестов.

А потом ТС родит какой-то лютый говнокод, в котором переменные переименовываются, меняются местами и бегают по потолку. Ещё и в прод где-нибудь это засунет или хотябы в курсач воткнёт (откуда будут списывать) и через год-другой на ЛОР придёт очередной страдалец с куском этого говнокода, который невозможно понять и противно читать и попросит помочь его саппортить. И какой-нибудь регистрант пятизвёздный вякнет, мол, «какое же говно этот баш, надо было сразу на божественном питоне4 писать».

И ведь наверняка конечная задача - какая-нибудь тривиальщина уровня «переименовать 1000 файлов», где на самом деле даже массивы не нужны.

Спасибо за внимание.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

А потом ТС родит какой-то лютый говнокод, в котором переменные переименовываются, меняются местами и бегают по потолку.

Плюсую.

Deleted
()
Ответ на: комментарий от anonymous

а так делать не надо:


for i in ` seq 1 10 `; do let "per_$i"=$i; done;
for i in ` seq 1 10 `; do echo "$per_$i"; done;
for i in ` seq 1 10 `; do echo `expr "$per_$i" + 1`; done;

anonymous
()
Ответ на: комментарий от Deleted

так я и не утверждал, что оно работает, как ожидается. Я явно указываю переменные в блоке проверки. В варианте ТС (мой первый скрипт) эта проверка ничего не возвращала, во втором варианте то, что ожидается.

Наверное, я тебя сейчас не понял. Весь код не буду приводить замени это

   eval per_$kof=$kof
   echo "per_$kof: $per_$kof"
на это
# здесь мы создаём переменную и смотрим её начальное значение
eval echo 'anymouze говорит 'per_$kof': '$((per_$kof))
# обращаться к переменной по имени "с коэффициентом" можно либо через eval, либо явно писать per_N -- но, тогда мы можем создать переменную
   eval per_$kof=$((kof+10) # теперь значение в переменной отличается от счётчика
   echo "per_$kof: $per_$kof" # здесь ТС ничего + счетчик выводит
   echo "zvezdochiot говорит ${per_}${kof}" # у тебя тоже самое
   sleep 1 
Дальше моя «явная тупая» проверка. Я вижу
anymouze говорит per_1: 0
per_1: 1
zvezdochiot говорит 1
anymouze говорит per_2: 0
per_2: 2
zvezdochiot говорит 2
anymouze говорит per_3: 0
per_3: 3
zvezdochiot говорит 3
anymouze говорит per_4: 0
per_4: 4
zvezdochiot говорит 4
anymouze говорит per_5: 0
per_5: 5
zvezdochiot говорит 5
anymouze говорит per_6: 0
per_6: 6
zvezdochiot говорит 6
anymouze говорит per_7: 0
per_7: 7
zvezdochiot говорит 7
anymouze говорит per_8: 0
per_8: 8
zvezdochiot говорит 8
anymouze говорит per_9: 0
per_9: 9
zvezdochiot говорит 9
anymouze говорит per_10: 0
per_10: 10
zvezdochiot говорит 10
stupid verify by anymouze
11
12
13
14
15
16
17
18
19
20
что по идее и хочет ТС.

anymouze ★★
()
Ответ на: комментарий от anymouze

echo «per_$kof: $per_$kof»
echo «zvezdochiot говорит ${per_}${kof}»

Не то. Разжевываю:

kof=1 => per_="" =>  $per_$kof=""1 => $per_$kof != ${per_1}
Deleted
()
Ответ на: комментарий от anonymous

Это не моя идея. ТС хочет. Меня только любопытство толкает писать этот ненужный и бесполезный код.

anymouze ★★
()

Помоему ТС скумекал про изменение значения переменой, неверно сформулировал вопрос, после чего ему начали давать ответы, что по его скумекиванию меняется только значение переменной, а не название переменной для последующих её значений.

anonymous
()
Ответ на: комментарий от Deleted

естественно... я ж написал, что к так поименнованной переменной можно обращаться только с помощью eval или явно писать имя (но тогда, мы можем её создать явно)

per_1=1 # явная обычная переменная
kof=2
eval  per_$kof='привет' # переменная названная именем с коэффициентом
eval echo per_$kof':'$per_$kof
kof=$(($kof+1))
# дальше bash ругается
per_$kof=33
$per_$kof=333
${per_}${kof}=3333

anymouze ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.