Possibile bug in Bash ?: foo () {echo “$ {var [0]}”; }; var = (bar baz) pippo


22

Sistema operativo : Ubuntu 16.04.3

Shell : Bash 4.3.48


So che è possibile modificare temporaneamente il contenuto di una variabile come in var=value command, essendo probabilmente IFS= read -r varil caso più notevole di questo.

E, grazie al wiki di Greg , capisco anche:

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

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

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

Ciò che sfugge alla mia comprensione è questo:

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

Per quanto ne so (e seguendo la logica degli esempi precedenti), dovrebbe stampare bar, no (bar baz).

Questo succede solo a me? È questo il comportamento previsto e mi manca qualcosa? O è un bug?


3
Forse ha qualcosa a che fare con il fatto che bash non supporta gli array come variabili ambientali?
Jesse_b,

3
@Jesse_b Forse. Anche se quando lo eseguo export var=(foo bar); echo "${var[0]}"stampa foo, no (foo bar).
nxnev,

1
Strano, ha funzionato anche per me. E il suo utilizzo exportmostra:declare -ax var=([0]="foo" [1]="bar")
Jesse_b

3
L'ambiente non può contenere array, AFAIK. Ad esempio, export i_am_array=(foo bar); /usr/bin/env | grep i_am_arraynon fornisce alcun output qui.
derobert il

3
Inoltre: foo() { declare -p var; } ; var=(bar baz) foodà la declare -x var="(bar baz)"conferma che viene trattato come una stringa, non un array
derobert il

Risposte:


19

Generalmente chiamando:

var=value cmd

dove cmdè una funzione non è portatile.

Con bash, questo funziona solo per variabili scalari (e con l' x=(...)analisi come un array ma assegnato come uno scalare) e ci sono una serie di problemi con l'ambito se lo fai, con ksh93e yash, funziona ma la definizione della variabile rimane in seguito. Con mksh, viene visualizzato un errore di sintassi. Nella shell Bourne, non ha funzionato affatto, anche per le variabili scalari.

Si noti inoltre che anche con variabili scalari, indipendentemente dal fatto che la variabile venga esportata all'interno della funzione (ovvero passata ai comandi eseguiti) varia da shell a shell (è in bash, yash, mksh, zsh, ma non in ksh, cenere).

Funziona solo come ti aspetteresti zsh. Si noti che gli zshindici di array iniziano da 1.

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

12

Non è solo un bug, sembra essere una funzionalità non implementata senza piani per esserlo mai. Questo post della mailing list del 2014 ha questo dal creatore:

Fortunatamente, in bash 4.3 (livello di patch 25), non puoi semplicemente -DARRAY_EXPORT e ottenere l'importazione / esportazione delle variabili di array. Il codice non viene compilato e, se lo risolvi, non si collega e, se lo risolvi, si finisce con il seguente problema.

È un sacco di problemi da affrontare solo per questo. Non ho piani per abilitare l'esportazione di array.

Estrarre dall'ultimo repository git per Bash ha questo in variables.c:

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

Suggerendo che qualunque cosa ci sia non è completa.


5
Qui, è per una funzione, quindi non si tratta di esportare nulla poiché non execve()è coinvolta alcuna chiamata di sistema. Cerca zshuna shell che supporti le funzioni di chiamata con un array temporaneamente impostato in questo modo.
Stéphane Chazelas il

@ StéphaneChazelas Ma l'ambiente cambia (aggiungendo una nuova variabile) e poi torna indietro, dopo che la funzione è stata completata (sto per questo caso:) my_var=one func_bar. Possiamo dire che si exportsta aggiungendo all'ambiente e quindi l'esportazione viene utilizzata qui, sotto il cofano? Guarda la mia risposta, ho aggiunto il codice dimostrativo.
MiniMax,

10

Dalla man bashsezione BUGS (la versione di bashè 4.3):

BUGS

   Array variables may not (yet) be exported.

Il codice successivo dimostra che esiste una variabile temporanea nell'ambiente, solo mentre la funzione è in esecuzione. Al termine della funzione, la variabile temporanea scompare.

### 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

Informazioni correlate:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.