簡単な質問です。 Bashシェルはシェルスクリプトを書くときのポインタの使用をサポートしますか?
${var[@]}
私は配列を繰り返すときにスプレッド表記に慣れています$var
が、これが配列インデックスを繰り返すためにポインタを使用しているかどうかはわかりません。 bashは他の言語と同様にメモリアドレスへのアクセスを提供しますか?
Bashがポインタの使用をサポートしていない場合、他のシェルは何をしますか?
答え1
ポインタ(位置を指すメモリ)は、Pythonであれシェルであれ、Cよりも高いレベルでは実際には役に立つ概念ではありません。オブジェクトへの参照は確かに高度な言語で有用であり、複雑なデータ構造を構築するために必要となるかもしれません。しかし、ほとんどの場合、メモリアドレスの観点から考えるのは低すぎるため、あまり使用できません。
Bash(および他のシェル)では、notationを使用して配列要素の値を取得し${array[index]}
、を使用して値を割り当てarray[index]=...
、を使用して配列の要素数を取得できます${#array[@]}
。括弧内の式は算術式です。仮想の例として、すべての配列メンバーに定数プレフィックスを追加できます。
for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
array[i]="foo-${array[i]}"
done
(インデックス以外の値にのみ関心がある場合はfor x in "${array[@]}" ; do...
問題ありません。)
そして関連またはまれな配列、数字を繰り返すことはあまり意味がありませんが、配列キー/インデックスを取得するために使用する必要があります${!array[@]}
。例えば
declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do
echo "${assoc[$i]}"
done
さらに、Bashには他の変数を間接的に指す2つの方法があります。
- 間接拡張、使用
${!var}
文法、値を持つ変数の値を使用します。名前にありvar
、 - 名前参照、使用が必要
declare
組み込み(またはksh
-互換同義語、typeset
)。declare -n ref=var
参照ref
変数var
。
Namerefsは、インデックス付けもサポートしています。これは、使用が配列として使用され、2番目の要素と呼ばれる変数を参照するためですarr=(a b c); declare -n ref=arr;
。${ref[1]}
b
${!p[1]}
p
Bashでは、namerefsは文字通り参照を意味します。名前、関数内で nameref を使用すると、指定された変数のローカル値が使用されます。これで印刷されますlocal value of var
。
#!/bin/bash
fun() {
local var="local value of var"
echo "$ref";
}
var="global var"
declare -n ref=var
fun
Bash FAQでは間接参照に関するより長い記事、また。
答え2
いいえ、bash
「ポインタ」はありませんが、参照があります。
$ spam="fred"
$ declare -n tripe=spam
$ echo $tripe
fred
$ tripe=juki
$ echo $spam
juki
bash
マニュアルページから:
declare
組み込みコマンドの-nオプションを使用して、nameref属性を変数に割り当てて、local
namerefまたは他の変数への参照を生成できます。これにより、変数を間接的に操作できます。 nameref変数が参照、割り当て、設定解除される、またはその属性が変更されるたびに(nameref属性自体を使用または変更する場合を除く)、nameref変数の値で指定された変数に対して実際にアクションが実行されます。 nameref は通常、シェル関数の名前が関数に引数として渡される変数を参照するために使用されます。たとえば、変数名をシェル関数の最初の引数として渡す場合は、次のようにします。declare -n ref=$1
関数内で、最初のパラメータとして渡された変数名を値として持つnameref変数refが生成されます。 refへの参照と割り当て、およびその属性への変更は、名前が$ 1に渡される変数への参照、割り当て、および属性の変更として扱われます。 forループの制御変数にnameref属性がある場合、単語リストはシェル変数リストになり、ループが実行されると、リスト内の各単語に名前参照が設定されます。 nameref属性は配列変数に割り当てることはできません。ただし、nameref変数は配列変数と添字配列変数を参照できます。組み込みの-nオプションを使用してNamerefの設定を解除できます
unset
。そうではなく、unset
nameref変数の名前を引数として実行すると、nameref変数が参照する変数は設定解除されます。
答え3
いいえ、シェルは「ポインタ」(Cで理解されているように)を使用しません。
配列はインデックスを使用できますが、echo "${array[2]}"
例@
の配列は実際には「ポインタ」ではありません。 「値の配列リスト」を表現する方法です。シェルパーサーが理解できるもの。次のような:
$ echo "$@"
すべての位置パラメータリストに展開します。
答え4
bash 整数インデックス配列は、次のように繰り返し定義してアクセスできます。
declare -a obj
obj+=("val1")
obj+=("val2")
for item in ${obj[@]}; do
echo "${obj[${item}]} ${item}"
done
Bashの関連または文字列ベースのインデックス配列には、次の繰り返し定義が必要です。
declare -A obj
obj["key1"]="val1"
obj["key2"]="val2"
for item in ${!obj[@]}; do
echo "${obj[${item}]} ${item}"
done
bashでのポインタとポインタの使用に関する質問に答えるために、コンパイルされたbashバイナリの内部関数はスタックに割り当てられたメモリへのポインタを使用し、実際にはeval
。http://tldp.org/LDP/abs/html/ivr.html)
用があるのでeval
安全上の危険がありますので注意して使用してください。