次のスクリプトがあります。
for chain in http https ssh
do
iptables -nvxL $chain | tail -1 | awk '{print $2}'
done
しかし、私が本当に望むのは、iptables
各反復のコマンド出力を異なる変数としてキャプチャすることです。名前現在の値と同じでなければなりませんchain
。
したがって、最初のループ反復(ここでは)の場合は、$chain
次のhttp
ようになりたいと思います。
http=$(iptables -nvxL http | tail -1 | awk '{print $2}')
次に私はこれが欲しい:
https=$(iptables -nvxL https | tail -1 | awk '{print $2}')
アイデアを得たことを願っていますが、どうすればいいかわかりません。
答え1
あなたの場合は、連想配列を使用します。
declare -A rules
for chain in http https ssh
do
rules[$chain]=$(iptables -nvxL $chain | tail -1 | awk '{print $2}')
done
その後、次のように出力を逆参照して出力にアクセスできます。
printf -- "%s\n" "${rules['http']}"
または
for chain in http https ssh
do
printf -- "%s\n" "${rules[$chain]}"
done
答え2
連想配列に対する答えは、ほぼ確実にあなたが望む方法です。
ただし、and(http
、および$ referencesを使用)という変数が必要な場合は、名前を含む変数にコマンド出力を割り当てることができます。https
ssh
$http
$https
ssh
printf -v
$chain
for chain in http https ssh; do
printf -v "$chain" '%s' "$(iptables -nvxL "$chain" | tail -1 | awk '{print $2}')"
done
によると、また参照してくださいこの回答、同じ目的を達成するために、typeset
以下を使用できます。declare
for chain in http https ssh; do
typeset "$chain"="$(iptables -nvxL "$chain" | tail -1 | awk '{print $2}')"
done
eval
この回答中に被害を受けた人は誰もいません。また、@penguin359の答えのように、ループから変数値を印刷するには、次のように使用できます。bash変数間接変数名の逆参照 - 繰り返しますが、eval
sは必要ありません。
for chain in http https ssh; do
echo ${!chain}
done
答え3
修正する:$2
例に含まれている内容を引用するのを忘れました。これでOPは要求どおりに動作します。また、この回答のポイントと使用法は、eval
複数の実装で標準のBourneシェル構文を使用して移植可能な例を提供することです。 bash、dash、zshで次のコードをすべてテストしました。 Dashは、Bourneシェル構文とより制限的で一貫性のある構文を使用するため、より良い移植性テストです。 Debian/Ubuntu のデフォルトシェルでもあります/bin/sh
。 Dashには合計はありませんtypeset
。printf -v
私はそれが醜いと思いますeval
が、Bourneシェルの最初のメカニズムであり、真の移植性を達成するための最良の方法です。
連想配列が良い方法だと思いますが、Bashに加えて他のBourneシェルに正確で移植可能な彼の元の質問に答えを提供したかったのです。動的変数名は、伝統的に次のように実行されます。
for chain in http https ssh; do
eval $chain="\"\$(iptables -nvxL $chain | tail -1 | awk '{print \$2}')\""
done
Bourneシェルの演算子eval
は、変数をコマンドに置き換えてから、完了するとコマンドで再実行(再評価)するために使用されます。コマンドを最初に置き換えた後、$chain変数と最初の参照セットが完了し、次のようになります。
http="$(iptables -nvxL http | tail -1 | awk '{print $2}')"
その後、これはコマンド拡張の変数割り当てとして評価されますiptables
。内部コマンドは単一引用符を使用するため、ステートメントを引用するために使用できないため、評価にはおよびを使用し、eval
結果"\"
コマンド\""
に必要に応じて二重引用符と一重引用符を渡します。コマンド拡張の周りに二重引用符は必要ないかもしれませんが、コマンドが複数の単語に拡張されると、いくつかのシェルの問題が発生します。これをダンプするには:
for chain in http https ssh; do
eval echo \$$chain
done
最初のドル記号が引用されて渡されます。その結果、ループを解放した後、次の3つのコマンドが実行されます。
echo $http
echo $https
echo $ssh