Vím, že Bash a Zsh podporují local
proměnné, ale existují systémy, které mají pouze shelly kompatibilní s POSIX. A local
je v POSIX shellech nedefinovaný.
Chci se tedy zeptat, které shelly podporují local
klíčové slovo pro definování lokálních proměnných?
Upravit :O shellech mám na mysli výchozí /bin/sh
shell.
Přijatá odpověď:
Není to tak jednoduché jako podpora local
nebo ne. Existuje mnoho variací v syntaxi a v tom, jak se to dělá mezi shelly, které mají jednu nebo druhou formu místního rozsahu.
Proto je velmi těžké přijít s normou, která bude souhlasit se všemi. Podívejte se na http://austingroupbugs.net/bug_view_page.php?bug_id=767, kde najdete úsilí POSIX v této oblasti.
místní rozsah byl přidán jako první v ksh na počátku 80. let.
Syntaxe pro deklaraci lokální proměnné ve funkci byla s typeset
:
function f {
typeset var=value
set -o noglob # also local to the function
...
}
(podpora funkcí byla do Bourne shellu přidána později, ale s jinou syntaxí (příkaz f() command
) a ksh
později také přidána podpora pro tento; Bourne shell nikdy neměl lokální rozsah (samozřejmě kromě přes subshells))
local
vestavěný AFAIK byl poprvé přidán do shellu Almquist (používaný v BSD, dash, busybox sh) v roce 1989, ale funguje výrazně odlišně od ksh
typeset
. ash
deriváty nepodporují typeset
jako alias pro local
, ale vždy můžete jeden definovat ručně.
bash a zsh přidaly typeset
s aliasem local
v roce 1989 a 1991.
ksh88 přidal local
jako nezdokumentovaný alias pro typeset
cca 1990 a pdksh a jeho deriváty v roce 1994. posh
(založeno na pdksh
) odstraněn typeset
(pro přísné dodržování zásad Debianu, které vyžadují local
, ale ne typeset
).
POSIX zpočátku protestoval proti specifikování typeset
na základě toho, že byl dynamický rozsah. Takže ksh93 (přepis ksh v roce 1993 Davidem Kornem) přešel na statický místo toho. Také v ksh93, na rozdíl od ksh88, se místní rozsah provádí pouze pro funkce deklarované pomocí ksh
syntaxe (function f {...}
), nikoli Bournovu syntaxi (f() {...}
) a local
alias byl odstraněn.
Nicméně ksh93v-beta a finální verze od AT&T lze zkompilovat s experimentálním „bash“ režimem (ve skutečnosti povoleno ve výchozím nastavení), který provádí dynamické škálování (v obtěžujících formách funkcí, včetně local
a typeset
), když ksh93
je vyvoláno jako bash
. local
se liší od typeset
v takovém případě v tom, že jej lze vyvolat pouze z funkce. Ten bash
režim bude ve výchozím nastavení v ksh2020 deaktivován pomocí local
/declare
aliasy na typeset
budou zachovány, i když bash režim není zkompilován (ačkoli stále se statickým rozsahem).
yash
(napsáno mnohem později), má typeset
(à la ksh88), ale má pouze local
jako alias od verze 2.48 (prosinec 2018).
@Schily spravuje potomka Bourne shellu, který byl nedávno vytvořen převážně v souladu s POSIX, nazvaný bosh
která podporuje místní rozsah od verze 2016-07-06 (s local
, podobně jako ash
).
Takže shelly podobné Bourneovi, které dnes mají nějakou formu lokálního rozsahu proměnných, jsou:
- ksh, všechny implementace a jejich deriváty (ksh88, ksh93, pdksh a deriváty jako posh, mksh, OpenBSD sh).
- ash a všechny jeho deriváty (NetBSD sh, FreeBSD sh, dash, busybox sh)
- bash
- zsh
- yash
- Bosh
Až k sh
různých systémů, všimněte si, že existují systémy, kde je POSIX sh
je v /bin
(většina) a další, kde není (jako Solaris, kde je v /usr/xpg4/bin
). Pro sh
implementace na různých systémech, které máme:
- ksh88:komerční Unices většinou odvozené od SysV (AIX, HP/UX, Solaris¹…)
- bash:většina systémů GNU/Linux, Cygwin, macOS
- ash:ve výchozím nastavení na Debianu a většině derivátů (včetně Ubuntu, Linuxu/Mintu), ačkoli může být administrátorem změněno na bash nebo mksh. NetBSD, FreeBSD a některé jejich deriváty (ne macOS).
- busybox sh:mnoho, ne-li většina vestavěných systémů Linux
- pdksh nebo odvozeniny:OpenBSD, MirOS
Nyní, kde se liší:
typeset
(ksh, pdksh, bash, zsh, yash) vslocal
(ksh88, pdksh, bash, zsh, ash, yash 2.48+).- statický (ksh93, v
function f {...}
funkce), vs dynamický rozsah (všechny ostatní shelly). Například zdafunction f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f
výstupy1
nebo2
. Podívejte se také naexport
atribut ovlivňuje rozsah vksh93
. - zda
local
/typeset
prostě udělá proměnnou místní (ash
,bosh
), nebo vytvoří novou instanci proměnné (jiné shelly). Například zdav=1; f() { local v; echo "${v:-empty}"; }; f
výstupy1
neboempty
(viz takélocalvar_inherit
možnost v bash 5.0 a vyšší). - u těch, které vytvářejí novou proměnnou, zda nová zdědí atributy (jako
export
) a/nebo typ a které z proměnné v rodičovském oboru. Například, zdaexport V=1; f() { local V=2; printenv V; }; f
vytiskne1
,2
nebo nic. - zda má tato nová proměnná počáteční hodnotu (prázdná, 0, prázdný seznam, v závislosti na typu,
zsh
) nebo není původně nastaveno. - zda
unset V
na proměnné v lokálním rozsahu ponechá proměnnouunset
, nebo jen loupe jedna úroveň rozsahu (mksh
,yash
,bash
za určitých okolností). Například zdav=1; f() { local v=2; unset v; echo "$v"; }
výstupy1
nebo nic (viz takélocalvar_unset
možnost v bash 5.0 a vyšší) - jako pro
export
, zda se jedná o klíčové slovo, nebo pouze vestavěné nebo obojí a za jakých podmínek je považováno za klíčové slovo. - jako pro
export
, zda jsou argumenty analyzovány jako normální argumenty příkazu nebo jako přiřazení (a za jakých podmínek). - zda můžete prohlásit místní proměnná, která byla v nadřazeném rozsahu pouze pro čtení.
- interakce s
v=value myfunction
kdemyfunction
sám deklarujev
zda místní nebo ne.
To jsou ty, na které teď myslím. Podívejte se na chybu austin group výše pro více podrobností.
Pokud jde o místní rozsah možností shellu (na rozdíl od proměnných ), skořápky, které jej podporují, jsou:
ksh88
(se syntaxí definice obou funkcí):provádí se ve výchozím nastavení, nevím o žádném způsobu, jak to zakázat.ash
(od roku 1989):slocal -
. To dělá$-
parametr (který ukládá seznam možností) local.ksh93
:nyní provedeno pouze profunction f {...}
funkce.zsh
(od roku 1995). Ssetopt localoptions
. Také semulate -L
aby byl režim emulace (a jeho sada možností) nastaven jako místní pro funkci.bash
(od roku 2016) slocal -
jako vash
.
Související:Binární a textový režim příkazu Md5sum?