Bogue possible dans Bash?: Foo () {echo “$ {var [0]}”; }; var = (bar baz) foo


22

OS : Ubuntu 16.04.3

Shell : Bash 4.3.48


Je sais qu'il est possible de changer temporairement le contenu d'une variable comme dans var=value command, étant probablement IFS= read -r varle cas le plus notable de cela.

Et, grâce au wiki de Greg , je comprends aussi:

# Why this
foo() { echo "$var"; }
var=value foo

# And this does work
var=value; echo "$var"

# But this doesn't
var=value echo "$var"

Ce qui échappe à ma compréhension, c'est ceci:

$ foo() { echo "${var[0]}"; }
$ var=(bar baz) foo
(bar baz)

Pour autant que je sache (et en suivant la logique des exemples précédents), il devrait imprimer bar, non (bar baz).

Est-ce que cela m'arrive seulement? Est-ce le comportement souhaité et il me manque quelque chose? Ou est-ce un bug?


3
Peut-être que cela a quelque chose à voir avec le fait que bash ne prend pas en charge les tableaux en tant que variables environnementales?
Jesse_b

3
@Jesse_b Peut-être. Bien que lorsque je lance, export var=(foo bar); echo "${var[0]}"il imprime foo, non (foo bar).
nxnev

1
Bizarre, cela a aussi fonctionné pour moi. Et son utilisation exportmontre:declare -ax var=([0]="foo" [1]="bar")
Jesse_b

3
L'environnement ne peut pas contenir de tableaux, AFAIK. Par exemple, export i_am_array=(foo bar); /usr/bin/env | grep i_am_arrayne donne aucune sortie ici.
derobert

3
Aussi: foo() { declare -p var; } ; var=(bar baz) foodonne la declare -x var="(bar baz)"confirmation qu'il est traité comme une chaîne, pas comme un tableau
derobert

Réponses:


19

Appelant généralement:

var=value cmd

cmdest une fonction n'est pas portable.

Avec bash, cela ne fonctionne que pour les variables scalaires (et avec x=(...)analysé en tant que tableau mais affecté en tant que scalaire) et il y a un certain nombre de problèmes avec la portée si vous le faites, avec ksh93et yash, cela fonctionne mais la définition de la variable reste après. Avec mksh, vous obtenez une erreur de syntaxe. Dans le shell Bourne, cela ne fonctionnait pas du tout, même pour les variables scalaires.

Notez également que même avec des variables scalaires, le fait que la variable soit ou non exportée dans la fonction (c'est-à-dire passée aux commandes en cours d'exécution) varie d'un shell à l'autre (c'est en bash, yash, mksh, zsh, mais pas en ksh, cendre).

Cela ne fonctionne que comme vous vous en doutez zsh. Notez que les zshindices de tableau commencent à 1.

bash-4.4$ zsh
$ a=(before value)
$ f() echo $a[1]
$ a=(temp value) f
temp
$ echo $a[1]
before

12

Ce n'est pas seulement un bug, il semble que ce soit une fonctionnalité non implémentée sans aucun plan de l'être. Ce message de la liste de diffusion de 2014 a ceci du créateur:

Heureusement, dans bash 4.3 (patchlevel 25), vous ne pouvez pas simplement -DARRAY_EXPORT et obtenir l'importation / exportation de variables de tableau. Le code ne compile pas, et si vous corrigez cela, il ne lie pas, et si vous corrigez cela, eh bien, vous vous retrouvez avec le problème suivant.

C'est une tonne de problèmes à traverser juste pour ça. Je n'ai pas l'intention d'activer l'exportation de tableaux.

Tirant du dernier dépôt git pour Bash a ceci dans variables.c:

  #  if ARRAY_EXPORT
        /* Array variables may not yet be exported. */

Suggérer que tout ce qui s'y trouve n'est pas complet.


5
Ici, c'est pour une fonction, il n'est donc pas question d'exporter quoi que ce soit car aucun execve()appel système n'est impliqué. Voir zshpour un shell qui prend en charge les fonctions d'appel avec un tableau temporairement défini de cette façon.
Stéphane Chazelas

@ StéphaneChazelas Mais l'environnement change (en ajoutant une nouvelle variable) puis revient en arrière, une fois la fonction terminée (je suis sur ce cas:) my_var=one func_bar. Peut-on dire que cela exportajoute à l'environnement et donc, l'exportation est utilisée ici, sous le capot? Regardez ma réponse, j'ai ajouté le code de démonstration.
MiniMax

10

À partir de la man bashsection BUGS de (la version de la bash4.3 est):

BOGUES

   Array variables may not (yet) be exported.

Le code suivant montre qu'une variable temporaire existe dans l'environnement, uniquement pendant l'exécution de la fonction. Une fois la fonction terminée, la variable temporaire disparaît.

### defining the "bar" function
### it pass all environment variables to the "grep" command
### and the "grep" prints the only "my_var" variable from it
bar() { env | grep my_var=; }

### calls the "bar" function with the temporary 
### variable "my_var" created and assigned.
my_var=one bar

my_var=one         ### The output. The environment contains the "my_var" variable

### checks, does the environment still have the "my_var" variable
### (It doesn't have.)
env | grep my_var=
                   ### The output is empty,
                   ### the environment doesn't contain the "my_var" variable

Informations connexes:

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.