Що таке непряме розширення? Що означає $ {! Var *}?


85

Я читаю " Баш-путівник для початківців ". Він говорить:

Якщо першим символом PARAMETERє знак оклику, Bash використовує значення змінної, сформованої з решти, PARAMETERяк ім'я змінної; потім ця змінна розширюється, і це значення використовується в решті заміни, а не значення PARAMETERсамої. Це відоме як непряме розширення.

Наведений приклад:

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

Я тут не зовсім розумію:

значення змінної, сформованої з решти PARAMETER

Як PARAMETERсправедливий !N*, тоді

Решта PARAMETER

просто N*. Як це могло утворити змінну? Баш шукав там усі можливі команди?

Відповіді:


110

Якщо ви читаєте bashдовідкову сторінку, це в основному підтверджує те, що ви заявили:

Якщо першим символом параметра є знак оклику ( !), вводиться рівень змінної непрямості. Bash використовує значення змінної, сформованої з решти параметра, як ім'я змінної; ця змінна потім розширюється, і це значення використовується в решті заміни, а не значення самого параметра. Це відоме як непряме розширення.

Однак читаючи звідти:

Винятком з цього є розширення ${!prefix*}та ${!name[@]}описані нижче.

${!prefix*}Імена, що відповідають префіксу. Розширюється до імен змінних, імена яких починаються префіксом, розділеними першим символом IFSспеціальної змінної.

Іншими словами, ваш конкретний приклад ${!N*}є винятком із правила, яке ви цитували. Це дійсно , однак, робота як рекламується в очікуваних випадках, таких як:

$ export xyzzy=plugh ; export plugh=cave

$ echo ${xyzzy}  # normal, xyzzy to plugh
plugh

$ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
cave

1
Дякую за відповідь. Чим більше я читаю "Посібник Bash для початківців", тим більше запитую себе, чи розуміє автор те, що вона пише.
LRDPRDX

23

Здається, є виняток, коли дана "непрямість" закінчується на a *, як це робиться тут. У цьому випадку він дає всі імена змінних, які починаються з вказаної вами частини (N тут). Bash може це зробити, оскільки він відстежує змінні і знає, які з них існують.

Справжня опосередкованість така:
скажімо, у мене є змінна, $VARIABLEвстановлена ​​на 42, і у мене є інша змінна, $NAMEвстановлена ​​на VARIABLE. ${!NAME}дасть мені 42. Ви використовуєте значення однієї змінної, щоб сказати вам назву іншої:

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42

5
Ого, хто знав, що так легко отримати відповідь на сенс життя, Всесвіту та всього іншого!
KomodoDave

3

Так, він шукає всі можливі розширення змінних після!. Якби ви зробили:

echo ${!NP*}

ви отримаєте лише NPX_PLUGIN_PATH .

Розглянемо наступний приклад:

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye

чи буде для інших змінних, які відповідають моєму *, також встановлено значення "до побачення"?
Ентоні

1
@Anthony Я спробував, і якщо ${!my*}розширюється до myA, myB, myA експортується зі своїм поточним значенням, а myB встановлюється на "до побачення" та експортується. Не дуже корисно.
GKFX

3

Ви потрапили у виняток у непрямій обробці, де, якщо останній символ *, всі змінні, що мають префікс, вказаний раніше, будуть повернуті.


Тож, крім *справи, це те саме, що ${${VAR}}?
chronospoon

1
@chronospoon, коротше записаний ${${VAR}}як ${$VAR}, не є законним, оскільки $VARповертає рядок, який не може слідувати за $знаком; щоб використовувати рядок як ім'я змінної, потрібно ввести один рівень опосередкованості (як цитується в самому оригінальному запитанні), тобто ви можете використовувати ${!VAR}, що робить саме те, що ви очікуєте (помилково, але зрозуміло) ${$VAR}.
Енріко

0

Ви можете звернутися до цього документа GNU щодо bash для отримання достовірної інформації

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-Expansion

Але в основному непряме розширення не виконується ${!prefix*} як один із винятків, у вашому прикладі N - префікс.

У Документі буде пояснено, що таке непряме розширення в bash

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