BashとZshが変数をサポートしていることを知っていますが、local
一部のシステムにはPOSIX準拠のシェルしかありません。local
POSIXシェルでは定義されていません。
local
その場合は、どのシェルがローカル変数のキーワード定義をサポートしているかを尋ねたいと思います。
編集する:シェルについては、デフォルトの/bin/sh
シェルを参照してください。
答え1
これはlocal
サポートやサポートされていないほど簡単ではありません。構文にはさまざまなバリエーションがあり、1つまたは別の形式のローカルスコープを使用するシェル間で実行される方法もあります。
そのため、誰もが同意できる基準を設定することは困難です。バラよりhttp://austingroupbugs.net/bug_view_page.php?bug_id=767この分野へのPOSIXの努力に感謝します。
ローカルスコープは1980年代初めにkshに最初に追加されました。
関数でローカル変数を宣言する構文は次のとおりですtypeset
。
function f {
typeset var=value
set -o noglob # also local to the function
...
}
(関数サポートは後でBourneシェルに追加されましたが、別の構文(f() command
)を使用し、ksh
その構文のサポートも後で追加されました。
AFAIKの組み込み機能は、local
1989年にAlmquistシェル(BSD、dash、busybox shで使用)に最初に追加されましたが、ksh
大きく異なる動作をしますtypeset
。デリバティブはエイリアスをash
サポートしていませんが、いつでも手動で定義できます。typeset
local
エイリアスはそれぞれ1989年と1991年にbashとzshに追加されましたtypeset
。local
ksh88は1990年頃にlocal
文書化されていない別名として追加され、typeset
1994年にはpdkshとその派生として追加されました。posh
(ベースpdksh
)削除されました(必要ですが必須ではないtypeset
場合はDebianポリシーを厳密に遵守するため)。local
typeset
指定に対するPOSIXの初期反対typeset
は次の通りであった。動的範囲指定。したがって、ksh93(David Kornの1993年のksh書き換え)は次のように変更されました。変化のない代わりに範囲指定。また、ksh93では、ksh88とは異なり、Bourne構文ksh
()ではなく構文()を使用してfunction f {...}
宣言された関数に対してのみローカルスコープが実行され、Aliasingが削除されました。f() {...}
local
local
しかし、AT&Tのksh93v -betatypeset
と最終バージョンは 。この場合との違いは、関数内でのみ呼び出すことができることです。ksh93
bash
local
typeset
bash
ksh2020ではデフォルトで無効になっています。しかし、local
/alias Bashモードがコンパイルされていないdeclare
場合でもtypeset
(まだ静的範囲がありますが)。
yash
typeset
(非常に遅く書かれています)(à la ksh88)がありますが、local
バージョン2.48(2018年12月)以降はエイリアスとしてのみ使用されました。
@ヒリー(悲しいことに誰ですか?2021年に死亡)は最近POSIXと互換性のあるBourneシェルの子孫を維持するために使用されます。bosh
local
ローカルスコープ(同様)はバージョン2016-07-06からサポートされていますash
。
したがって、ある種のローカル変数スコープを使用する今日のBourneのようなシェルは次のようになります。
- ksh、すべての実装、およびその派生物(ksh88、ksh93、pdkshおよびposh、mksh、OpenBSD shなどの派生物)。
- ashおよびすべての派生物(NetBSD sh、FreeBSD sh、dash、busybox sh)
- 強く打つ
- 扱いにくい
- ヤッシュ
- ボッシュ
さまざまなシステムでは、一部のシステム(ほとんど)にsh
POSIXが含まれており、他のシステムには含まれていません(Solarisなど)。さまざまなシステムに実装するには、次のものがあります。sh
/bin
/usr/xpg4/bin
sh
- ksh88: ほとんどの SysV 派生商用 Unices (AIX、HP/UX、Solaris1...)
- bash:ほとんどのGNU / Linuxシステム、Cygwin、macOS
- ash:デフォルトでは、Debianおよびほとんどの派生製品(Ubuntu、Linux / Mintを含む)では、管理者はこれをbashまたはmkshに変更できます。 NetBSD、FreeBSD、および一部の派生製品(macOSを除く)
- busybox sh:ほとんどではありませんが、多くの組み込みLinuxシステム
- pdkshまたは派生物:OpenBSD、MirBSD、Android
今の違いは次のとおりです。
typeset
(ksh、pdksh、bash、zsh、yash)およびlocal
(ksh88、pdksh、bash、zsh、ash、yash 2.48+)。- サポートされるオプションのリストです。
- 静的(ksh93、
function f {...}
関数内)および動的範囲(他のすべてのシェル)。たとえば、function f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f
出力1
と。このプロパティがどのように影響するかを2
ご覧ください。export
ksh93
- 何でも
local
/typeset
ちょうど変数を作る地元の(ash
、bosh
)または変数の新しいインスタンスを作成します(他のシェル)。たとえば、またはv=1; f() { local v; echo "${v:-empty}"; }; f
出力かどうか(bash 5.0以降のオプションを参照)。1
empty
localvar_inherit
- 新しい変数を生成する変数の場合、新しい変数が継承されるかどうかプロパティ(例:)および
export
/または型と親範囲の変数から取得した型。たとえば、export V=1; f() { local V=2; printenv V; }; f
印刷するか1
どう2
かを印刷するかどうかです。 - この新しい変数に初期値(型に応じてnull、0、空のリスト
zsh
)があるか、最初に設定されていないか。 unset V
その変数をローカルスコープの変数にそのままにするのunset
か、それともそのままにするのかシェル最初のレベルの範囲(場合によっては、、mksh
)。たとえば、出力するかどうか(bash 5.0以降のオプションを参照)yash
bash
v=1; f() { local v=2; unset v; echo "$v"; }
1
localvar_unset
- for と同じように、
export
キーワードであるか、組み込みキーワードであるか、両方であるか、どの条件でキーワードと見なされるかを確認します。 - forと同様に、
export
引数が通常のコマンド引数または割り当てられた値に解析されるかどうか(およびどの条件下でも)です。 - あなたは言うことができますか?地元の親範囲で読み取り専用の変数です。
v=value myfunction
自体がローカルまたは非ローカルでmyfunction
宣言された場所との相互作用。v
それが私が今考えているすべてです。詳細については、上記のAustinグループエラーを確認してください。
シェルのローカル範囲についてオプション(大変わりやすい)、これをサポートするシェルは次のとおりです。
ksh88
(2つの関数定義構文を使用):デフォルトでは実行されますが、無効にする方法はありません。ash
(1989年以降):と同じですlocal -
。$-
パラメータ(保存されているオプションのリスト)をローカルパラメータに設定します。ksh93
function f {...}
:これは機能に対してのみ実行されます。zsh
(1995年から)。そしてsetopt localoptions
。emulate -L
シミュレーションモード(および対応するオプションセット)を機能ローカライゼーションに設定することもできます。bash
(2016年以降)にlocal -
似ていますash
が、管理対象オプションにのみ適用され、set
管理対象オプションには適用されませんshopt
。
sh
1 SolarisのPOSIXは/usr/xpg4/bin/sh
(関数ローカルオプションを含む多くの適合性のバグがありますが)です。/bin/sh
Solaris 10より前はBourneシェル(ローカルスコープなし)で、Solaris 11以降はksh93です。
答え2
Stéphaneの回答に関する追加情報を取得するには、サブシェルを使用してローカルを取得します。影響。実際のPOSIXシェルにアクセスすることはできませんが、これはbusyboxで機能します。中括弧の代わりに括弧を使用してash
関数を宣言します。これにより、関数がサブシェルで実行されます。()
{}
func() (
echo "in func, before declaring: x=$x"
x=10
echo "in func, after declaring: x=$x"
)
x=5
echo "before func: x=$x"
func
echo "after func: x=$x"
出力
before func: x=5
in func, before declaring: x=5
in func, after declaring: x=10
after func: x=5
これは、関数がグローバル変数にアクセスでき、関数内で変数を設定してもグローバル変数が変更されないことを示します。私は時々ディレクトリを変更または変更したいときに$IFS
この手法を使用しますcd
が、これらの操作がプログラムの残りの部分に影響を与えたくありません。