変数宣言時のコマンド置換実行の防止

変数宣言時のコマンド置換実行の防止

だから、最近コマンド置換を使って変数を宣言するとき、私は次のように言えることがわかりました。

var=$(echo "this is running" > test; cat test)

それから〜する実行(ファイルを生成しますtest)。まだ(技術的に)呼び出していませんが、

var=$(echo "this is running" > test; cat test)
echo "$var" # is where i would "normally" call the variable

変数で宣言するときにコマンド置換が実際に実行されるのを防ぐにはどうすればよいですか?走る私はその変数を呼び出すと?

PS:これが悪い例であることは明らかですが、「役に立たない猫」と「役に立たないイエロー」にもかかわらず、私が意味するものをよく示しています。

答え1

コンテンツが動的に生成される変数が欲しいようです。

bashサポートしていないksh93トピック、またはzshの動的に名前が付けられたディレクトリまたはmksh価値の代替これにより作業が簡単になりますが、namerefを使用してこの方法を使用できます。

var_generator() { date --iso-8601=ns; }
var_history=()
typeset -n var='var_history[
  ${##${var_history[${#var_history[@]}]=$(var_generator)}},${#var_history[@]}-1
]'

ここではvar配列要素への参照として定義され$var_history、配列インデックスが動的に計算され、任意のコードを実行できることを活用します(ここでは関数を実行し、そのvar_generator出力を配列の新しい要素に割り当てるために使用されます)。

それから:

bash-5.1$ echo "$var"
2021-03-23T13:36:43,243211696+00:00
bash-5.1$ echo "$var"
2021-03-23T13:36:45,517726619+00:00

$(var_generator)ここでは使用できますが、複雑すぎるようです。しかし、1つの利点は、${var#pattern}while bash(with zsh)will not let you doなどの作業を続けることができることです${$(cmd)#pattern}

答え2

実際に呼び出したので実行されます。通常、遅延評価されるMakeの変数とは異なり、シェル拡張が発生します。これによりvar='$(...)'コマンド置換は実行されませんが、後で実行するのも難しくなります。これはfoo=$bar、後で最終的に使用されるときに値を確認するのではなく、当時の値をコピーする方法と似ています。barfoo

簡単な代替は、関数を使用することです。たとえば、次は約5秒間隔で2つの日付を印刷する必要があります。

getdate() {
    date +"%F %T"
}
a=$(getdate)
sleep 5
b=$(getdate)
echo "$a $b"

関数の使用の欠点は、パラメータ拡張に使用できる文字列操作を使用できないことです。${(getdate)% *}出力の最初の部分だけを得ることはできません。foo=$(getdate); foo=${foo% *};

関連情報