W powłoce Bourne'a, która obsługuje zmienną tablicową, możemy użyć analizy składniowej, aby sprawdzić, czy zmienna jest tablicą.
Wszystkie poniższe polecenia zostały uruchomione po uruchomieniu a=(1 2 3)
.
zsh
:
$ declare -p a
typeset -a a
a=( 1 2 3 )
bash
:
$ declare -p a
declare -a a='([0]="1" [1]="2" [2]="3")'
ksh93
:
$ typeset -p a
typeset -a a=(1 2 3)
pdksh
i jego pochodna:
$ typeset -p a
set -A a
typeset a[0]=1
typeset a[1]=2
typeset a[2]=3
yash
:
$ typeset -p a
a=('1' '2' '3')
typeset a
Przykład w bash
:
if declare -p var 2>/dev/null | grep -q 'declare -a'; then
echo array variable
fi
To podejście jest zbyt pracochłonne i wymaga odrodzenia podpowłoki. Korzystanie z innych wbudowanych powłok, takich jak =~
in [[ ... ]]
, nie wymaga podpowłoki, ale wciąż jest zbyt skomplikowane.
Czy istnieje łatwiejszy sposób na wykonanie tego zadania?
Odpowiedzi:
Nie sądzę, że możesz, i nie sądzę, że to naprawdę robi jakąkolwiek różnicę.
Że robi to samo w jednej z
ksh93
ibash
. Wygląda na to, że prawdopodobnie wszystkie zmienne są tablicami w tych powłokach, a przynajmniej jakakolwiek zwykła zmienna, której nie przypisano specjalnych atrybutów, ale nie sprawdziłem wiele z nich.Do
bash
podręcznika mówi o różnych zachowań na tablicy w funkcji zmiennej łańcuchowej podczas korzystania z+=
zadania, ale potem żywopłoty i stwierdza, że matryca zachowuje się inaczej niż tylko w związek kontekście przypisania.Wskazuje również, że zmienna jest uważana za tablicę, jeśli jakiemukolwiek indeksowi przypisano wartość - i wyraźnie obejmuje możliwość łańcucha zerowego. Powyżej widać, że zwykłe przypisanie zdecydowanie skutkuje przypisaniem indeksu dolnego - i tak myślę, że wszystko jest tablicą.
Praktycznie możesz użyć:
... aby wyraźnie wskazać zmienne, którym przypisano tylko jeden indeks dolny o wartości 0.
źródło
${a[1]-not array}
da radę, prawda?bash
instrukcją: Zmienna tablicowa jest uważana za ustawioną, jeśli indeksowi przypisano wartość. Ciąg zerowy jest prawidłową wartością. Jeśli jakikolwiek indeks dolny ma przypisaną tablicę według specyfikacji. W praktyce też nie, bo możesza[5]=x
. Chyba[ 1 -eq "${#a[@]}" ] && [ -n "${a[0]+1}" ]
może działać.Więc skutecznie chcesz tylko środkową część
declare -p
bez śmieci?Możesz napisać makro, takie jak:
abyś mógł:
(Zwykła funkcja nie zadziała, jeśli będziesz chciał użyć jej w zmiennych lokalnych funkcji).
Z aliasami
źródło
alias vartype="$VARTYPE"
... lub po prostu nie definiując$VARTYPE
wcale - powinien działać, prawda? powinieneś potrzebować tylko tegoshopt
,bash
ponieważ jest to niezgodne ze specyfikacją dotyczącąalias
rozszerzania skryptów.W Zsh
źródło
echo ${(t)var}
jest prostsze. Dzięki za to.Aby przetestować zmienną var, za pomocą
Możliwe jest sprawdzenie, czy istnieje więcej niż jeden indeks tablicy:
Jeśli pierwsza wartość indeksu nie jest równa zero:
Jedynym trudnym zamieszaniem jest sytuacja, gdy istnieje tylko jedna wartość indeksu i ta wartość wynosi zero (lub jedna).
W tym stanie można zastosować efekt uboczny próby usunięcia elementu tablicy ze zmiennej, która nie jest tablicą:
Działa to poprawnie w przypadku bash:
W przypadku zsh indeks może wymagać 1 (chyba że aktywny jest tryb kompatybilny).
Sub-shell jest potrzebny, aby uniknąć efektu ubocznego wymazania indeksu 0 var.
Nie znalazłem sposobu, aby działał w ksh.
Edytuj 1
Ta funkcja działa tylko w bash4.2 +
Edytuj 2
Działa to również tylko dla bash4.2 +
Uwaga: Daje to fałszywie pozytywne wyniki, jeśli var zawiera testowane ciągi.
źródło
( unset "var[0]" 2>/dev/null; ) && echo "var is an array."
poprawności raportów var jest tablicą, gdy var jest ustawiony navar=()
tablicę z zerowymi elementami. Działa dokładnie tak samo, jak deklarować.grep -E
zamiast,grep -P
aby uniknąć zależności od GNU grep.-a
w następujący sposób:declare -airl var='()'
. Dlatego test grep będzie działał .W przypadku bash jest to trochę hack (choć udokumentowane): spróbuj użyć,
typeset
aby usunąć atrybut „array”:(Nie możesz tego zrobić w
zsh
, pozwala to przekonwertować tablicę na skalar,bash
jest to wyraźnie zabronione).Więc:
Lub w funkcji, zwracając uwagę na ostrzeżenia na końcu:
Zwróć uwagę na użycie
typeset -g
(bash-4.2 lub nowszy), jest to wymagane w ramach funkcji, abytypeset
(syn.declare
) Nie działało podobnie jaklocal
i blokowało wartość, którą próbujesz sprawdzić. To również nie obsługuje typów funkcji „zmiennych”, możesz dodać kolejny test gałęzi, używając wtypeset -f
razie potrzeby.Inną (prawie pełną) opcją jest użycie tego:
Jest jednak jeden niewielki problem: tablica z pojedynczym indeksem 0 odpowiada dwóm powyższym warunkom. Jest to coś, do czego mikeserv również się odwołuje, bash tak naprawdę nie ma twardego rozróżnienia, a niektóre z nich (jeśli zaznaczysz Dziennik zmian) można winić za ksh i zgodność z tym, jak
${name[*]}
lub jak się${name[@]}
zachowywać na nie-macierzy.Więc częściowe rozwiązanie jest:
W przeszłości korzystałem z tej wersji:
to też potrzebuje podpowłoki.
Jeszcze jedną potencjalnie przydatną techniką jest
compgen
:Spowoduje to wyświetlenie listy wszystkich indeksowanych tablic, jednak tablice asocjacyjne nie są obsługiwane specjalnie (do wersji bash-4.4) i pojawiają się jako zmienne zwykłe (
compgen -A variable
)źródło
typeset +a
również błąd w ksh. Jednak nie w Zsh.Krótka odpowiedź:
Dla dwóch powłok, które wprowadziły ten zapis (
bash
iksh93
), zmienna skalarna jest tylko tablicą z jednym elementem .Żadne z nich nie wymaga specjalnej deklaracji, aby utworzyć tablicę. Wystarczy przypisanie, a zwykłe przypisanie
var=value
jest identycznevar[0]=value
.źródło
bash -c 'unset var; var=foo; typeset -p var'
. Czy odpowiedź bash zgłasza tablicę (wymaga -a) ?. Teraz porównać z:bash -c 'unset var; var[12]=foo; typeset -p var'
. Dlaczego jest różnica? Odp .: Powłoka utrzymuje (na dobre lub na złe) pojęcie, które zmienne są skalarami lub tablicami. Powłoka ksh łączy obie koncepcje w jedną.Wbudowane
array
yash ma kilka opcji, które działają tylko ze zmiennymi tablicowymi. Przykład:-d
opcja zgłosi błąd w zmiennej innej niż tablica:Możemy więc zrobić coś takiego:
To podejście nie zadziała, jeśli zmienna tablicowa jest tylko do odczytu . Próba zmodyfikowania zmiennej tylko do odczytu prowadzącej do błędu:
źródło
źródło