bash zshの${!FOO}への間接参照と同じものは何ですか?

bash zshの${!FOO}への間接参照と同じものは何ですか?

${!FOO}で二重置換を実行しますbash。つまり、FOOの(文字列)値を取得し、変数名として使用することを意味します。
zshこの機能はサポートされていません。

bashこのタスクをおよびで同じにする方法はありますかzsh

背景:

次の環境変数のリストがあります。

PATH MAIL EDITOR

変数名を最初に印刷してから、その値を印刷しようとしています。

これは機能しますbashが、次の場合は機能しませんzsh

for VAR in LIST
do
        echo $VAR
        echo ${!VAR}
done

おそらくある意味では「古い方法」でなければなりませevalんが、うまく機能させることはできません。

for VAR in LIST
do
        echo $VAR
        echo `eval \$$VAR`
done

私はなぜ任意の深い交換を実行できないのか、必要な${${VAR}}場合でも決して理解できないので、それについての説明は良いでしょう。${${${VAR}}}

答え1

元の質問に対するProfpatschのコメントは、${(p)FOO}間接変数参照の内容を出力する例を提供します。ロゴが正しくないか、スペルが間違っています。小文字のpの代わりに大文字のPを使用する必要があります。使用: ${(P)FOO}

以下は目的の出力を生成する必要があります。

#! /bin/zsh
LIST=(PATH MAIL EDITOR)
for VAR in ${LIST}
do
    print -r -- "${VAR}:  ${(P)VAR}"
done

~からzshexpnマンページセクション -パラメータ拡張フラグ:

  This forces the value of the parameter name to be interpreted as a further
  parameter name,  whose  value  will  be used where appropriate.  Note that
  flags set with one of the typeset family of commands (in particular case
  trans‐formations) are not applied to the value of name used in this fashion.

  If used with a nested parameter or command substitution, the result of that
  will be taken as a parameter  name  in the  same  way.   For  example,  if
  you  have  `foo=bar'  and `bar=baz', the strings ${(P)foo}, ${(P)${foo}}, and
  ${(P)$(echo bar)} will be expanded to `baz'

ある時点で期待した結果が出ない理由を読んでいました${${${VAR}}}が、今は見つかりません。次のことができます。

first="second" ; second="third" ; third="fourth" ; fourth="fifth"
print -r -- ${(P)${(P)${(P)first}}}
fifth

答え2

bashとzshの両方に間接拡張を実行する方法がありますが、異なる構文を使用します。

;を使用すると、間接拡張を簡単に実行できますeval。これはすべてのPOSIXとほとんどのBourneシェルで動作します。値にシェルに特別な意味を持つ文字が含まれている場合は、正しく引用する必要があります。

eval "value=\"\${$VAR}\""
echo "$VAR"
echo "$value"

${${VAR}}どのシェルでも実装されている機能ではないため、機能しません。中括弧内の内容は除外構文規則に従う必要があります${VAR}。 (zshではこれはサポートされている構文ですが、他のことを行います。入れ子になった置換は、同じ値に対して連続変換を実行します。値ペアに対して2つのID変換を実行するのと${${VAR}}同じです。)$VAR

答え3

体験版を正しく使用していません。あなたの例では、「$」(たとえば「$ VALUE」)の前にある$ VAR値がコマンドとして実行されます。それはあなたが望むものではありません。別の変数から名前を取得した変数の拡張を計算しようとしています。

$ for i in `echo PATH MAIL EDITOR`; 
    do eval moo="\${$i}" 
    echo $moo 
done
/usr/local/sbin:/usr/local/bin:/usr/sbin:/u (...)
/var/mail/root
nano

答え4

{ba,z}sh解決策

これは{ba、z}shで有効な関数です。私はそれがPOSIXとも互換性があると思います。

次のメッセージが表示されると、警告が表示されます。

  • 空の入力
  • 1つ以上の引数
  • 設定されていない変数名
# Expand the variable named by $1 into its value. Works in both {ba,z}sh
# eg: a=HOME $(var_expand $a) == /home/me
var_expand() {
  if [ "$#" -ne 1 ] || [ -z "${1-}" ]; then
    printf 'var_expand: expected one non-empty argument\n' >&2;
    return 1;
  fi
  eval printf '%s' "\"\${$1?}\""
}

関連情報