Что такое косвенное расширение? Что означает ${! Var *}?
Я читаю "Bash Guide for Beginners". В нем говорится:
Если первый символ PARAMETER
является восклицательным знаком, Bash использует значение переменной, сформированной из остальной части PARAMETER
, как имя переменной; эта переменная затем расширяется и это значение используется в остальной части подстановки, а не как значение PARAMETER
. Это называется косвенным расширением.
Приведенный пример:
franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
Я не совсем понимаю здесь:
значение переменной, сформированной из остальной части PARAMETER
Поскольку PARAMETER
является просто !N*
, тогда
остальная часть PARAMETER
является просто N*
. Как это могло образовать переменную? Выбрали ли Bash всю возможную команду?
Ответы
Ответ 1
Если вы читаете справочную страницу 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
Ответ 2
Как представляется, существует исключение, когда данная "косвенность" заканчивается на *
, как здесь. В этом случае все имена переменных начинаются с указанной вами части (N
здесь).
Bash может сделать это, потому что он отслеживает переменные и знает, какие из них существуют.
Истинная косвенность такова:
Скажем, у меня есть переменная $VARIABLE
, установленная на 42
, и у меня есть другая переменная $NAME
, установленная на VARIABLE
. ${!NAME}
даст мне 42
. Вы используете значение одной переменной, чтобы указать имя другого:
$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42
Ответ 3
Да, он ищет все возможные расширения переменных после!. Если вы сделали:
echo ${!NP*}
вы получите только NPX_PLUGIN_PATH
.
Рассмотрим следующий пример:
:~> export myVar="hi"
:~> echo ${!my*}
myVar
:~> export ${!my*}="bye"
:~> echo $myVar
bye
Ответ 4
Вы попали в исключение в обработке косвенности, где, если последний символ *
, будут возвращены все переменные, у которых есть префикс, указанный выше.