Je sais que Bash et Zsh supportent local variables, mais certains systèmes n'ont que des shells compatibles POSIX. Et local n'est pas défini dans les shells POSIX.
Je veux donc demander quels shells prennent en charge local mot clé pour définir les variables locales ?
Modifier :À propos des shells, je veux dire la valeur par défaut /bin/sh coquille.
Réponse acceptée :
Ce n'est pas aussi simple que de prendre en charge local ou pas. Il existe de nombreuses variations dans la syntaxe et la façon dont cela se fait entre les shells qui ont une forme ou une autre de portée locale.
C'est pourquoi il est très difficile de trouver une norme qui convienne à tous. Voir http://austingroupbugs.net/bug_view_page.php?bug_id=767 pour l'effort POSIX sur ce front.
la portée locale a été ajoutée pour la première fois dans ksh au début des années 80.
La syntaxe pour déclarer une variable locale dans une fonction était avec typeset :
function f {
typeset var=value
set -o noglob # also local to the function
...
}
(la prise en charge de la fonction a été ajoutée au shell Bourne plus tard, mais avec une syntaxe différente (commande f() command ) et ksh ajout d'un support pour celui-là également plus tard ; le shell Bourne n'a jamais eu de portée locale (sauf bien sûr via les sous-shells))
Le local builtin AFAIK a été ajouté pour la première fois au shell Almquist (utilisé dans les BSD, dash, busybox sh) en 1989, mais fonctionne de manière très différente de ksh est typeset . ash les dérivés ne prennent pas en charge typeset comme alias de local , mais vous pouvez toujours en définir un à la main.
bash et zsh ont ajouté typeset alias local en 1989 et 1991 respectivement.
ksh88 a ajouté local en tant qu'alias non documenté de typeset vers 1990 et pdksh et ses dérivés en 1994. posh (basé sur pdksh ) supprimé typeset (pour une stricte conformité à la politique Debian qui requiert local , mais pas typeset ).
POSIX s'est initialement opposé à la spécification de typeset au motif qu'il était dynamique portée. Donc ksh93 (une réécriture de ksh en 1993 par David Korn) est passé à statique portée à la place. Aussi dans ksh93, contrairement à ksh88, la portée locale n'est effectuée que pour les fonctions déclarées avec le ksh syntaxe (function f {...} ), pas la syntaxe Bourne (f() {...} ) et le local alias a été supprimé.
Cependant, la version ksh93v-beta et finale d'AT&T peut être compilée avec un mode "bash" expérimental (en fait activé par défaut) qui effectue une portée dynamique (dans les deux formes de fonctions, y compris avec local et typeset ) lorsque ksh93 est invoqué en tant que bash . local diffère de typeset dans ce cas, en ce sens qu'il ne peut être appelé qu'à partir d'une fonction. Ce bash le mode sera désactivé par défaut dans ksh2020 si le local /declare alias vers typeset sera conservé même lorsque le mode bash n'est pas compilé (mais toujours avec une portée statique).
yash (écrit beaucoup plus tard), a typeset (à la ksh88), mais n'a eu que local comme alias depuis la version 2.48 (décembre 2018).
@Schily maintient un descendant du shell Bourne qui a récemment été rendu principalement conforme à POSIX, appelé bosh qui prend en charge la portée locale depuis la version 2016-07-06 (avec local , similaire à ash ).
Ainsi, les shells de type Bourne qui ont une certaine forme de portée locale pour les variables aujourd'hui sont :
- ksh, toutes les implémentations et leurs dérivés (ksh88, ksh93, pdksh et dérivés comme posh, mksh, OpenBSD sh).
- ash et tous ses dérivés (NetBSD sh, FreeBSD sh, dash, busybox sh)
- bash
- zsh
- yash
- bosh
En ce qui concerne le sh de différents systèmes vont, notez qu'il existe des systèmes où le POSIX sh est dans /bin (la plupart), et d'autres où ce n'est pas (comme Solaris où c'est dans /usr/xpg4/bin ). Pour le sh mise en œuvre sur divers systèmes que nous avons :
- ksh88 :la plupart des Unix commerciaux dérivés de SysV (AIX, HP/UX, Solaris¹…)
- bash :la plupart des systèmes GNU/Linux, Cygwin, macOS
- ash :par défaut sur Debian et la plupart des dérivés (y compris Ubuntu, Linux/Mint) mais peut être modifié par l'administrateur en bash ou mksh. NetBSD, FreeBSD et certains de leurs dérivés (pas macOS).
- busybox sh :de nombreux systèmes Linux embarqués, sinon la plupart
- pdksh ou dérivés :OpenBSD, MirOS
Maintenant, où ils diffèrent :
typeset(ksh, pdksh, bash, zsh, yash) vslocal(ksh88, pdksh, bash, zsh, cendre, yash 2.48+).- statique (ksh93, dans
function f {...}fonction), vs portée dynamique (tous les autres shells). Par exemple, sifunction f { typeset v=1; g; echo "$v"; }; function g { v=2; }; fsorties1ou2. Voir aussi comment l'exportl'attribut affecte la portée dansksh93. - si
local/typesetrend juste la variable locale (ash,bosh), ou crée une nouvelle instance de la variable (autres shells). Par exemple, siv=1; f() { local v; echo "${v:-empty}"; }; fsorties1ouempty(voir aussi lelocalvar_inheritoption dans bash 5.0 et supérieur). - avec ceux qui créent une nouvelle variable, si la nouvelle hérite des attributs (comme
export) et/ou type et lesquels de la variable dans la portée parent. Par exemple, siexport V=1; f() { local V=2; printenv V; }; fimprime1,2ou rien. - si cette nouvelle variable a une valeur initiale (vide, 0, liste vide, selon le type,
zsh) ou est initialement non défini. - si
unset Vsur une variable dans une portée locale laisse la variableunset, ou simplement peler un niveau de portée (mksh,yash,bashdans certaines circonstances). Par exemple, siv=1; f() { local v=2; unset v; echo "$v"; }sorties1ou rien (voir aussi lelocalvar_unsetoption dans bash 5.0 et supérieur) - comme pour
export, s'il s'agit d'un mot-clé ou seulement d'un simple élément intégré ou les deux et dans quelles conditions il est considéré comme un mot-clé. - comme pour
export, si les arguments sont analysés comme des arguments de commande normaux ou comme des affectations (et dans quelles conditions). - si vous pouvez déclarer local une variable qui était en lecture seule dans la portée parent.
- les interactions avec
v=value myfunctionoùmyfunctiondéclare lui-mêmevcomme local ou non.
C'est à eux que je pense tout à l'heure. Vérifiez le bogue du groupe Austin ci-dessus pour plus de détails.
En ce qui concerne la portée locale des options du shell (par opposition aux variables ), les shells qui le supportent sont :
ksh88(avec les deux syntaxes de définition de fonction) :fait par défaut, je ne connais aucun moyen de le désactiver.ash(depuis 1989) :aveclocal -. Cela fait le$-paramètre (qui stocke la liste des options) local.ksh93:maintenant seulement fait pourfunction f {...}fonctions.zsh(depuis 1995). Avecsetopt localoptions. Aussi avecemulate -Lpour que le mode d'émulation (et son ensemble d'options) soit rendu local à la fonction.bash(depuis 2016) aveclocal -comme dansash.
En relation:Mode binaire et texte de la commande Md5sum?