~からhttps://unix.stackexchange.com/a/381782/674
たとえば、
integer() { typeset -gi "$1"; }
変数を整数にするには//を使用できます
mksh
。yash
zsh
bash
まだ宣言されていない変数に対してのみ機能します。地元の発信者:$ bash -c 'f() { declare a; integer a; a=1+1; echo "$a"; }; integer() { typeset -gi "$1"; }; f' 1+1 $ bash -c 'f() { integer a; a=1+1; echo "$a"; }; integer() { typeset -gi "$1"; }; f' 2
でも、でもあり
export var
ませtypeset -x var
んtypeset -gx var
。export
変数がすでに存在する場合は、新しい変数を宣言せずに属性を追加します。readonly
対。とtypeset -r
同じ
バッシュの場合、
f
最初の例では、内部宣言とは異なるものをinteger a
宣言したり、a
内部宣言にグローバルスコープを持たせたりするにはどうすればよいですか。なぜ出力されますか?a
f
a
f
1+1
f
2番目の例では、グローバルスコープがinteger a
宣言されていますかa
?なぜ出力されますか2
?
zshについても同じ質問です。しかし、最初の例がbashの2
代わりに出力されるのはなぜですか1+1
?
私は正しいですか?
- 少なくとも例では、bashとzshの両方が動的スコープを使用していますか?
-g
bashとzshのオプションは、typeset
存在しない変数をグローバルスコープとして宣言するか、既存の変数をグローバルスコープに変更することを意味しますか?
ありがとうございます。
答え1
プログラミング言語で静的範囲、たとえば、他のほとんどのプログラミング言語(例:C)、
すべての関数にはグローバルスコープとローカルスコープがあります。関数に表示される変数は、関数専用またはグローバル変数です。
関数はそのうちの1つだけにアクセスできます。それローカルまたはグローバル変数。参照に渡す以外に、他の関数(またはその呼び出し元)の変数にアクセスすることはできません。
プログラミング言語で動的範囲の指定、
関数は呼び出し元の変数を見ることができ、関数呼び出しツリーの各関数には範囲があります。範囲指定は、変数が重なっているロシアのマトリョーシカ人形と同じです。
この範囲スタックではグローバル範囲の唯一の特別な点は、範囲が最も下にあることです。ただし、関数が呼び出しツリーの関数によってローカル変数としてマスクされている場合、関数はその範囲内の変数を必ずしも見ることはできません。したがって、グローバルスコープとローカルスコープはありません。
ここの歴史を知ることが役に立ちます。
1.ksh93
存在する
ksh93
、ksh 構文を使用して宣言された関数(function f {...}
)、次のように静的範囲。typeset
関数内で宣言された変数は、その関数に対してローカルです。a=global_a function f { typeset a=f_a g } function g { echo "$a" } f
出力されます
global_a
。typeset -i var
機能でタイプが変更されました。地元のvar
変数が関数スコープでまだインスタンス化されていない場合、変数はインスタンス化されます。存在する
ksh93
、Bourne 構文を使用して宣言された関数(f() {...}
)範囲指定はまったくありません。これに関して、関数のコードは次のようになります。埋め込み関数呼び出し元では、その中に現れるすべての変数は呼び出し元と同じ範囲を持つため、呼び出しツリーでksh構文を使用してグローバルまたはローカルに宣言された最上位関数の場合。typeset
変数は最上位関数で宣言されます(または呼び出しツリーにksh構文関数がない場合はグローバルに)。たとえば、ksh-syntax関数では、すべての変数はプライベートまたはグローバル変数であるため、
integer
asを実装するにはbash
次のようにする必要があります。integer() { typeset -i "$1"; }
それはBourne 関数構文の使用これは範囲指定をまったく行いません。
またはksh構文の使用:
function integer { typeset -i "$1"; }
ただし、次のように呼び出されます。
. integer var
(つまり、使用
.
.
、整数コードは、スクリプトで()を呼び出すときと同様に、呼び出し元のコンテキストで解釈されます。source
または使用ksh構文:
function integer { typeset -ni "$1"; }
どこ変数が参照として渡されます。
-n
Cや他のほとんどのプログラミング言語と同じです。
2. 他のすべての Bourne 同様のシェル
他のすべてのBourne様シェル(ksh88を含むksh93は完全に書き直されました静的スコープの変更は、POSIX標準に含まれる機能の前提条件です(少なくとも考慮されます)。) 実装動的範囲の指定。
関数内で
typeset
なく宣言された変数は、その関数のローカル範囲を持ちます。-g
たとえば、
typeset -i var
変数をローカル(現在の関数の範囲内)で宣言して設定します。整数属性。たとえば、上部のコードではすべて出力です
f_a
。つまり、g
ローカル変数が実際に表示されますf
。別の例として、変数が
f
宣言されていない場合にg
呼び出されますh
。h
var
地元のg
その範囲内ではの変数を見ることができ、ローカルで宣言されていないf
場合の変数を見ることもでき、最下位の範囲の変数を見ることもできます。g
var
全体的に
bash
、、、、、、zsh
yash
mksh
次のコマンドを使用すると、関数にローカルにすることなく、関数内の変数の型または値を変更できます。typeset -g
。integer
引用した例のこの機能と同じです。しかし、シェルによって異なります。存在する
mksh
、、、yash
zsh
、typeset -g
下の変数には影響しません(グローバル) 範囲ですが 現在定義されている範囲内で。たとえば、whileは
typeset -i var
ローカル変数(現在の関数範囲内)を宣言して設定します。整数プロパティ、typeset -gi var
後半のみが実行されます(範囲には影響しませんvar
)。たとえば、関数が上記の
integer
関数を呼び出して、次のように整数プロパティを変数に追加する場合:f() { local myvar integer myvar ... }
integer
変更したい属性それmyvar
認識されず、アクセスできないグローバル範囲の変数ではない変数。存在する
bash
、typeset -g
変数に影響を与えるインスタンスグローバル(最下位レベル)範囲。それが意味するのはですがg
、 のような動的範囲ではうまく動作しませんbash
。たとえば、質問の最初の例では、出力は
1+1
整数属性が変数に追加されなかったことを示します。に追加されましたㅏグローバルスコープの変数ですが、a
関数がアクセスできる変数ではありません。f