Как я могу получить доступ к переменным, которые последовательно именуются циклом, оставаясь внутри цикла?

Я пытаюсь понять, возможно ли создать набор переменных, пронумерованных на основе другой переменной (используя eval) в цикле, а затем вызвать ее до завершения цикла.

В качестве примера я написал скрипт с именем question (первая команда показывает содержимое переменной $tab)

(23:32:12\[[email protected])
[~/bin]$ listQpsk 40|grep -w [1-4]
40 SMANHUBAQPSK1          1    1344      1195        88
40 SMANHUBAQPSK1          2    1668      1470        88
40 SMANHUBAQPSK1          3    1881      1539        81
40 SMANHUBAQPSK1          4    1686      1409        83


(23:18:42\[[email protected])
[~/bin]$ cat question
#!/usr/bin/bash
tab=`listQpsk 40|grep -w [1-4]`
seq=1
num=4
until [[ $seq -gt $num ]];do
eval count$seq=`echo "$tab"|grep -w $seq|awk '{print $5}'`
seq=$(($seq+1))
done
echo $count1
echo $count2
echo $count3
echo $count4

Когда я запускаю это, я получаю

(23:32:23\[[email protected])
[~/bin]$ ./question 
1195
1471
1538
1409

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

until [[ $seq -gt $num ]];do
eval count$seq=`echo "$tab"|grep -w $seq|awk '{print $5}'`
seq=$(($seq+1))
echo "$count$seq"
done

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


person Community    schedule 23.06.2009    source источник


Ответы (4)


Используйте косвенность:

until [[ $seq -gt $num ]];do
    var="count$seq"
    eval $var=$(echo "$tab"|awk -v seq=$seq '$3==seq {print $5}') # awk loves to do grep's job
    let seq+=1    # another way
    echo "${!var}"    # indirection
done

Нет необходимости в другом eval.

person Dennis Williamson    schedule 23.06.2009
comment
Это сработало отлично. Я не уверен, что понимаю часть косвенности. Но это сработало и так, как вы написали, и так же, как echo $var - person ; 24.06.2009
comment
echo $var даст, например, count1. echo ${!var} возвращает содержимое var, которое будет равно 1195. echo ${!var} работает аналогично echo $(eval echo \$$var) - person Dennis Williamson; 24.06.2009

Не совсем отвечая на ваш вопрос, но... знаете ли вы, что в bash есть переменные массива?

seq=1
num=4
until [[ $seq -gt $num ]];do
count[$seq]=`echo "$tab"|grep -w $seq|awk '{print $5}'`
seq=$(($seq+1))
done
echo ${count[*]}

Или без массивов:

seq=1
num=4
until [[ $seq -gt $num ]];do
eval count$seq=`echo "$tab"|grep -w $seq|awk '{print $5}'`
eval echo \$count$seq
seq=$(($seq+1))
done
person John Kugelman    schedule 23.06.2009
comment
Я знаю о них, но я еще не начал превращать их в сценарии. 0 Формальное обучение + полный рабочий день в качестве системного администратора означает, что мне обычно приходится осваивать новые навыки, поскольку они мне нужны. Я стараюсь не забегать слишком далеко вперед, потому что боюсь, что не усвою это. Шикарный ответ однако. Увидеть синтаксис массива в том, что я уже в основном понимаю, — огромная помощь в моем общем понимании. Кроме чистоты, есть ли преимущество в этом случае? Количество встроенных и внешних команд по-прежнему такое же, нет? - person ; 23.06.2009
comment
Я бы посчитал это правильным способом сделать это. Однако синтаксис может быть довольно уродливым, о чем свидетельствует оператор echo. Без массивов вам придется бросить больше оценок (согласно ответу cma). Кстати, я прочел man bash страницу дюжину раз сверху донизу, и каждый раз, когда я перечитываю ее снова, я все еще нахожу новую потрясающую статью «Где ты был всю мою жизнь». ;-) - person John Kugelman; 23.06.2009

Да, вот так (по крайней мере, в bash):

$ count1=xyz
$ seq=1
$ value=`eval echo \$\{count$seq\}`
$ echo $value
person Community    schedule 23.06.2009

Попробуй это:

varName=a
for i in 1 2 3
do
   eval $varName$i=stuff
   eval var=\$$varName$i
   echo $var
done

некоторые версии оболочки также позволяют использовать ${!var} для косвенной ссылки на переменные.

person Charles Ma    schedule 23.06.2009
comment
Ой, исправлено, так что теперь он делает то, что хочет :) - person Charles Ma; 23.06.2009