Что такое косвенная экспансия?Что означает $ {! Var *}? - PullRequest
66 голосов
/ 15 декабря 2011

Я читаю " Руководство по Bash для начинающих ". Там написано:

Если первый символ PARAMETER является восклицательным знаком, Bash использует значение переменной, сформированной из оставшейся части PARAMETER, в качестве имени переменной; эта переменная затем раскрывается, и это значение используется в остальной части замещения, а не в значении PARAMETER. Это известно как косвенное расширение.

Пример, приведенный ниже:

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

Я не совсем понимаю здесь:

значение переменной, образованной из остатка PARAMETER

Поскольку PARAMETER это просто !N*, то

остальное PARAMETER

это просто N*. Как это могло сформировать переменную? Bash обыскал там все возможные команды?

Ответы [ 5 ]

85 голосов
/ 15 декабря 2011

Если вы читаете справочную страницу 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
19 голосов
/ 15 декабря 2011

Кажется, есть исключение, когда данная «косвенность» заканчивается на *, как здесь.В этом случае он дает все имена переменных, которые начинаются с указанной вами части (N здесь).Bash может сделать это, потому что он отслеживает переменные и знает, какие из них существуют.

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

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42
3 голосов
/ 15 декабря 2011

Да, он ищет все возможные расширения переменных после!.Если бы вы сделали:

echo ${!NP*}

, вы получите только NPX_PLUGIN_PATH.

Рассмотрим следующий пример:

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye
2 голосов
/ 15 декабря 2011

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

0 голосов
/ 26 марта 2019

Вы можете обратиться к этому документу GNU для bash для получения достоверной информации

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

Но в основном косвенное расширение не выполняется на ${!prefix*}, как одно из исключений, в вашем примере N - префикс.

Документ объяснит, что такое косвенное расширение в bash

...