Poiché Bash, quando è in esecuzione nella modalità set -o nounset
(ovvero set -u
), può considerare gli array vuoti come non impostati indipendentemente dal fatto che siano stati effettivamente assegnati un valore vuoto, è necessario prestare attenzione quando si tenta di espandere un array: una delle soluzioni alternative consiste nel verificare se la lunghezza dell'array è zero. Per non parlare del fatto che ottenere il numero di elementi in un array è un'operazione comune di per sé.Ottieni la lunghezza di un array vuoto o non impostato quando è attiva l'opzione "nounset"
Durante lo sviluppo con Bash 4.2.47 (1) -release in openSUSE 42.1, sono abituati a quella dimensione dell'array ottenendo con ${#ARRAY_NAME[@]}
riesce quando array è vuoto o disinserito. Tuttavia, mentre controllava il mio script con Bash 4.3.46 (1) -release in FreeBSD 10.3, si è scoperto che questa operazione potrebbe fallire con il messaggio di errore generico "variabile non associata". Fornire il valore predefinito per l'espansione non sembra funzionare per la lunghezza dell'array. Fornire catene di comando alternative sembra funzionare, ma non all'interno di una funzione chiamata attraverso un'espansione subshell - le funzioni si chiudono appena dopo il primo errore. Cos'altro può esserci di aiuto qui?
consideri il seguente esempio:
function Size()
{
declare VAR="$1"
declare REF="\${#${VAR}[@]}"
eval "echo \"${REF}\" || echo 0" 2>/dev/null || echo 0
}
set -u
declare -a MYARRAY
echo "size: ${#MYARRAY[@]}"
echo "size: ${#MYARRAY[@]-0}"
echo "Size: $(Size 'MYARRAY')"
echo -n "Size: "; Size 'MYARRAY'
Nell'ambiente openSUSE, tutte echo
linee di uscita 0
, come previsto. In FreeBSD, lo stesso risultato è possibile solo quando all'array viene assegnato esplicitamente un valore vuoto: MYARRAY=()
; in caso contrario, entrambe le query inline nelle prime due righe falliscono, la terza riga viene emessa solo Size:
(il che significa che il risultato dell'espansione è vuoto) e solo l'ultima riga viene completata completamente grazie all'outdoor || echo 0
- tuttavia il passaggio attraverso lo schermo è non è ciò che è solitamente inteso quando si cerca di ottenere la lunghezza dell'array.
Ecco la sintesi delle mie osservazioni:
Bash 4.2 Bash 4.3
openSUSE FreeBSD
counting elements of unset array OK FAILED
counting elements of empty array OK OK
content expansion of unset array FAILED FAILED
content expansion of unset array(*) OK OK
content expansion of empty array FAILED FAILED
content expansion of empty array(*) OK OK
(* with fallback value supplied)
Per me, che sembra piuttosto inconsistente. Esiste una vera soluzione a prova di futuro e multipiattaforma per questo?
Aggiungi output di echo $ -' alla tua domanda. – Cyrus
@Cyrus È 'huB' in entrambi i sistemi quando si esegue uno script,' himBH' quando si è in riga di comando. –
Perché non fare semplicemente 'set + u', quindi fare i controlli necessari, quindi' set -u'? –