Z uwagi na fakt, że Bash, działając w trybie set -o nounset
(alias set -u
), może uznać puste tablice za niezaładowane, niezależnie od tego, czy zostały one faktycznie przypisane pusta wartość, należy zachować ostrożność podczas próby rozszerzenia tablicy - jednym z obejść jest sprawdzenie, czy długość tablicy wynosi zero. Nie wspominając już o tym, że uzyskanie liczby elementów w tablicy jest wspólną operacją samą w sobie.Uzyskaj długość pustej tablicy lub anuluj jej ustawienie, gdy działa opcja "słownik"
Podczas pracy z Bash 4.2.47 (1) - wypuszczam w openSUSE 42.1, przyzwyczaiłem się do tego, że uzyskanie rozmiaru tablicy z ${#ARRAY_NAME[@]}
powiedzie się, gdy tablica jest pusta lub unset. Jednak podczas sprawdzania mojego skryptu za pomocą Bash 4.3.46 (1) - w FreeBSD 10.3 okazało się, że operacja ta może zakończyć się niepowodzeniem z ogólnym komunikatem o błędzie "niezwiązana zmienna". Zapewnienie domyślnej wartości rozszerzenia nie wydaje się działać dla długości tablicy. Zapewnienie alternatywnych łańcuchów poleceń wydaje się działać, ale nie w funkcji wywoływanej przez rozszerzenie podpórki - funkcje kończą się po pierwszej awarii. Co jeszcze może tu być jakiejkolwiek pomocy?
Rozważmy następujący przykład:
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'
w środowisku openSUSE, wszystkie linie wyjściowe 0
echo
, jak oczekiwano. W FreeBSD ten sam wynik jest możliwy tylko wtedy, gdy tablicy jawnie przypisano pustą wartość: MYARRAY=()
; w przeciwnym razie obydwa zapytania śródliniowe w pierwszych dwóch wierszach zawodzą, trzecia linia po prostu wyprowadza Size:
(co oznacza, że wynik rozwinięcia jest pusty), a tylko ostatnia linia kończy się całkowicie dzięki zewnętrznemu || echo 0
- jednak przekazanie wyniku do ekranu jest nie to, co zwykle ma na celu uzyskanie długości tablicy.
Oto podsumowanie moich obserwacji:
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)
Dla mnie to wygląda dość niespójne. Czy istnieje w tym celu rozwiązanie przyszłościowe i wieloplatformowe?
proszę dodać wyjście 'echo $ -' do Twojego pytania. – Cyrus
@Cyrus Jest to 'huB' w obu systemach podczas uruchamiania skryptu,' himBH' w linii poleceń. –
Dlaczego nie po prostu zrobić 'set + u', a następnie wykonać niezbędne kontrole, a następnie' set -u'? –