Визначте змінні з ім'ям змінної


11

Що не так з цим сценарієм? Я намагаюся визначити A1 = 1, B1 = 1, C1 = 1

LIST="A B C"
for x in $LIST
do
    "$x"1=1
done

і результат:

./x.: line 7: A1=1: command not found
./x.: line 7: B1=1: command not found
./x.: line 7: C1=1: command not found

1
Я не думаю, що ти можеш створювати змінні в bash, як це. Це те, для чого потрібні масиви.
Jakuje

3
Використовуйте eval "$x"1=1. Хоча, як зазначив Джакує, масиви, ймовірно, краще підходять для цього випадку.
Андреа Корбелліні

@AndreaCorbellini Ви повинні написати це як відповідь.
Sparhawk

Відповіді:


21

Призначення змінної має вигляд імені змінної, за яким слідує знак рівності, за яким слід (необов'язково) значення.

Це дійсне завдання:

ABC=123

"$x"1=1не є дійсним призначенням, оскільки "$x"1це не ім'я змінної. Це може бути Eval закінчив інститут по імені змінної, але це не так . Справжня оболонка вважає, що це команда.

Один із способів зробити те, що ви хочете досягти, це такий:

eval "$x"1=1

Інший спосіб в башті (але не в інших оболонках):

declare "$x"1=1

Або також (знову лише для удару):

let "$x"1=1

(У вашому випадку немає великої різниці.)

Але, як зазначив Джакує в коментарях , ви, мабуть, хочете перейти з масивами, якщо у вашій оболонці є (ksh, bash або zsh).


Для повноти:

  • evalвиконує довільні команди. Отже, якщо в правій частині знака рівності у вас є змінна, яка розширюється на якусь команду, ця команда буде виконана. Наступний код:

    x=a
    y='$(echo hello)'
    eval "$x=$y"
    

    еквівалентно a=hello.

  • declareце bash вбудований для призначення змінних і не виконує жодної команди. Наступний код:

    x=a
    y='$(echo hello)'
    declare "$x=$y"
    

    еквівалентно a='$(echo hello)'.

  • letподібний тому declare, що він не виконує команди. Але всупереч declare, letможе використовуватися для арифметичних операцій:

    let a="1 + 2"

    еквівалентно a=3.


Навіть ABC = 123недійсний. Тому що до та після equal(=)знаку додається пробіл .
Mahendran Sakkarai

3

У bash FAQ є запис про опосередкованість. У більшості випадків використання ви повинні використовувати асоціативний або індексований масив. Ви також можете використовувати

func_call_by_reference() { # Bash 4.3
    typeset -n ref=$1   # nameref to the variable named by the caller
    ref=( "val1" "val2" ... )  # return an array by reference
}

Дивіться цю запис у FAQ, щоб отримати більше варіантів для цього, уникаючи безладного evalцитування.


0

Ви можете використовувати такий код, як наступний. У вашому коді оболонка виконується "$x"1=1як команда, оскільки вона не є дійсним призначенням змінної.

LIST="A B C"
for x in $LIST
do
    a=$(echo "$x"1)
    let $a=1
done

Яку оболонку ви використовуєте? Використовуючи bosh bash 4.1.7 та 4.3.11, я отримую помилки, command not found <varname>=1коли намагаюся це зробити (очевидно, що <varname> є значенням, в якому я зберігався a)
Eric Renouf

як пояснив @Andrea Corbellini, ми повинні використовувати let, оголосити або eval для присвоєння значення ..
AVJ

1
вам тут не потрібно echo! Просто a="$x"1. Також letє арифметичним контекстом, тому ви можете присвоювати йому лише числа.
Пітер Кордес

declare $a=foobarпрацює.
Пітер Кордес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.