typeset
はksh
のlocal
だと思っていましたが、これは_ksh93
_で失敗しますが、他のすべてのtypeset
対応シェル(bash、 yash、zsh、pdksh)
_#!/bin/ksh -ex
foo(){
typeset a b
a=0; b=1
return
}
a=a; b=b
foo
#confirm that the globals didn't change
[ "$a" = a ]
[ "$b" = b ]
_
何ができますか?
typeset
はksh93のprivate
(動的スコープを実行するPerl
ではなく、my
のlocal
のような静的スコープを使用)は、宣言された関数に対してのみです。 ksh関数定義スタイルの使用:
function foo {
typeset var=whatever
...
}
ボーン構文(または.
コマンド(ところで、kshスタイルの関数でも使用できます))では、スコープはありません($1
、$2
..を除く)。もちろん$#
)。したがって、Bourneスタイルの関数を使用して、親コンテキストで値を取得したり、変数の値またはタイプを変更したりできます(ただし、kshスタイルでtypeset -n
を使用することもできます)。
Ksh88では、typeset
はkshとBourneの両方の関数定義スタイルで動的スコープを実行していました。 David Kornによると、POSIXは、kshの変数スコープが動的(劣っていると見なされる)であることに基づいて指定しなかったため、静的スコープに変更しました。 ksh93
(完全な書き換え)の場合。
しかし、その間に、他のシェルは変数スコープを実装し、それらはすべてdynamicスコープを使用してksh88を模倣しました。
zsh
にprivate
キーワードが追加され、local
/typeset
に加えてksh93
と同様のスコープを持ち、ksh88
。
静的スコープと動的スコープの違いを確認するには、以下を比較してください。
"$Shell" -c 'function f { typeset a=1; g; echo "$a"; }
function g { echo "$a"; a=2; }
a=0; f'
$Shell
== ksh93
出力の場合:
0
1
そしてksh88
またはbash
出力:
1
2
zsh
:
$ zsh -c 'zmodload zsh/param/private
f() { private a=1; g; echo $a;}
g() { echo $a; a=2; }
a=0; f'
0
1
bash
、zsh
、ksh88
ksh93
、pdksh
、yash
またはに移植可能なコードでローカルスコープを使用できるようにするにはdash
/FreeBSD
sh、あなたができること:
[ -n "$BASH_VERSION" ] && shopt -s expand_aliases
alias shdef= kshdef='#'
if type typeset > /dev/null 2>&1; then
alias mylocal=typeset
if (a=1; f() { typeset a=2; }; f; [ "$a" = 2 ]); then
alias shdef='#' kshdef='function'
fi
else
alias mylocal=local
fi
そして、関数を次のように宣言します。
kshdef foo
shdef foo()
{
mylocal var
var=value
...
}
いずれにせよ、さまざまなシェルでのlocal
の動作には多くの違いがあります。上記の動的な考慮と静的な考慮のほかに、変数が最初に未設定または空の値を取得するか、親スコープから値を継承するかです。そして、readonly
/unset
がキーワードであるか組み込みであるかに関係なく、local
、typeset
との相互作用があります(split + glob処理に影響します)...
ksh93
でkshスタイルの関数定義を使用することには、他にも影響があります。詳細については、manページを参照してください。
sh
のローカルスコープを標準化するPOSIXの取り組み。