BashとZshがlocalをサポートしていることを知っています 変数ですが、POSIX互換のシェルしかないシステムもあります。そしてlocal POSIXシェルでは未定義です。
そこで、どのシェルがlocalをサポートしているかを尋ねたいと思います。 ローカル変数を定義するためのキーワード?
<ストライク>編集 :シェルについて私はデフォルトの/bin/shを意味します シェル。
承認された回答:
localをサポートするほど簡単ではありません か否か。構文にはさまざまなバリエーションがあり、ローカルスコープのいずれかの形式を持つシェル間でどのように実行されるかが異なります。
そのため、すべてに同意する基準を考案することは非常に困難です。その面でのPOSIXの取り組みについては、http://austingroupbugs.net/bug_view_page.php?bug_id=767を参照してください。
ローカルスコープは、80年代初頭にkshで最初に追加されました。
関数でローカル変数を宣言する構文は、typesetを使用していました。 :
function f {
typeset var=value
set -o noglob # also local to the function
...
}
(関数のサポートは後でBourneシェルに追加されましたが、構文が異なります(f() command )およびksh 後でそのサポートも追加しました。 Bourneシェルにはローカルスコープがありませんでした(もちろんサブシェル経由を除く))
local 組み込みのAFAIKは、1989年にAlmquistシェル(BSD、dash、busybox shで使用)に最初に追加されましたが、kshとは大幅に異なる動作をします。 のtypeset 。 ash 派生物はtypesetをサポートしていません localのエイリアスとして 、ただし、いつでも手動で定義できます。
bashとzshがtypesetを追加しました localのエイリアス それぞれ1989年と1991年に。
ksh88がlocalを追加しました typesetの文書化されていないエイリアスとして 1990年頃、1994年のpdkshとその派生物。posh (pdkshに基づく )typesetを削除しました (localを必要とするDebianポリシーに厳密に準拠するため 、ただしtypesetではありません 。
POSIXは当初、typesetの指定に反対しました 動的であるという理由で スコーピング。そのため、ksh93(1993年にDavid Kornがkshを書き直したもの)を staticに切り替えました。 代わりにスコーピング。また、ksh88とは対照的に、ksh93では、ローカルスコープはkshで宣言された関数に対してのみ実行されます。 構文(function f {...} )、ボーン構文ではありません(f() {...} )およびlocal エイリアスが削除されました。
ただし、AT&Tのksh93v-ベータ版と最終バージョンは、動的スコーピング(localを含む面倒な形式の関数)を実行する実験的な「bash」モード(実際にはデフォルトで有効)でコンパイルできます。 およびtypeset )ksh93の場合 bashとして呼び出されます 。 local typesetとは異なります その場合、関数内からのみ呼び出すことができます。そのbash localを使用すると、ksh2020ではデフォルトでモードが無効になります。 /declare typesetのエイリアス bashモードがコンパイルされていない場合でも保持されます(ただし、静的スコープは使用されます)。
yash (ずっと後で書かれています)、typesetがあります (àlaksh88)が、localしかありませんでした バージョン2.48(2018年12月)以降のエイリアスとして。
@Schilyは、最近ほとんどPOSIXに準拠するようになった、boshと呼ばれるBourneシェルの子孫を維持しています。 バージョン2016-07-06以降のローカルスコープをサポートします(localを使用) 、ashに似ています 。
したがって、今日の変数のローカルスコープの形式を持つボーンのようなシェルは次のとおりです。
- ksh、すべての実装とその派生物(ksh88、ksh93、pdksh、およびposh、mksh、OpenBSD shなどの派生物)。
- ashとそのすべての派生物(NetBSD sh、FreeBSD sh、dash、busybox sh)
- バッシュ
- zsh
- ヤシュ
- bosh
shまで さまざまなシステムがありますが、POSIX shが存在するシステムがあることに注意してください。 /binにあります (ほとんど)、およびそうでないその他の場所(/usr/xpg4/binにあるSolarisなど) )。 shの場合 さまざまなシステムでの実装:
- ksh88:ほとんどのSysV派生の商用Unices(AIX、HP / UX、Solaris¹…)
- bash:ほとんどのGNU / Linuxシステム、Cygwin、macOS
- ash:デフォルトではDebianおよびほとんどの派生物(Ubuntu、Linux / Mintを含む)ですが、管理者はbashまたはmkshに変更できます。 NetBSD、FreeBSDおよびそれらの派生物のいくつか(macOSではない)。
- busybox sh:ほとんどではないにしても多くの組み込みLinuxシステム
- pdkshまたは派生物:OpenBSD、MirOS
さて、それらが異なるところ:
typeset(ksh、pdksh、bash、zsh、yash)とlocal(ksh88、pdksh、bash、zsh、ash、yash 2.48+)。- static(ksh93、in
function f {...}関数)、vs動的スコーピング(他のすべてのシェル)。たとえば、function f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f1を出力します または2。exportの方法もご覧ください 属性はksh93のスコープに影響します 。 localかどうか /typeset変数をローカルにするだけです (ash、bosh)、または変数(他のシェル)の新しいインスタンスを作成します。たとえば、v=1; f() { local v; echo "${v:-empty}"; }; f1を出力します またはempty(localvar_inheritも参照してください。 bash 5.0以降のオプション)。- 新しい変数を作成する変数を使用して、新しい変数が属性を継承するかどうか (
exportのように )および/またはタイプ、および親スコープの変数からのタイプ。たとえば、export V=1; f() { local V=2; printenv V; }; f1を出力します 、2または何も。 - その新しい変数に初期値があるかどうか(空、0、空のリスト、タイプに応じて、
zsh)または最初は設定されていません。 -
unset Vかどうか ローカルスコープ内の変数で、変数をunsetのままにします 、または単にはがす 1レベルのスコーピング(mksh、yash、bash状況によっては)。たとえば、v=1; f() { local v=2; unset v; echo "$v"; }1を出力します または何もありません(localvar_unsetも参照してください bash 5.0以降のオプション) -
exportのように 、それがキーワードであるか、単なる組み込みであるか、またはその両方であるか、どのような条件下でキーワードと見なされるか。 -
exportのように 、引数が通常のコマンド引数として解析されるか、割り当てとして解析されるか(およびどのような条件下で)。 - ローカルを宣言できるかどうか 親スコープで読み取り専用だった変数。
-
v=value myfunctionとの相互作用 ここで、myfunctionそれ自体がvを宣言します ローカルかどうか。
それが私が今考えているものです。詳細については、上記のオースティングループのバグを確認してください。
シェルのローカルスコープに関する限りオプション (変数とは対照的に )、それをサポートするシェルは次のとおりです:
-
ksh88(両方の関数定義構文を使用):デフォルトで実行されますが、無効にする方法はわかりません。 -
ash(1989年以降):local -。$-になります パラメータ(オプションのリストを格納する)ローカル。 -
ksh93:function f {...}に対してのみ実行されるようになりました 機能。 -
zsh(1995年以降)。setopt localoptionsを使用 。emulate -Lも使用します エミュレーションモード(およびそのオプションのセット)を関数に対してローカルにするため。 -
bash(2016年以降)local -ashのように 。
関連:Md5sumコマンドのバイナリおよびテキストモード?