A tömböket a Tömbök fejezetben mutattuk be. Ebben a dokumentumban további módokat mutatunk be a tömbök használatára.
Az előző, tömbökről szóló fejezetben láttad a "${myarray[@]}" kifejezést az @ indexszel, amellyel a tömböt az egyes elemeire lehet bontani.
Néha azonban az összes elemet egyetlen stringgé szeretnéd összefűzni.
Ehhez a * indexet használd:
echo "${myarray[*]}"
A kiterjesztést kötelező kettős idézőjelbe tenni.
A Bash az IFS beépített változó első karakterét használja elválasztóként.
Alapértelmezés szerint a $IFS szóközből, tabulátorból és újsor karakterből áll.
myarray=(one two three four)
mystring="${myarray[*]}"
declare -p mystring
# => declare -- mystring="one two three four"
Az IFS változót módosítva más elválasztó karaktert is használhatunk:
myarray=(one two three four)
IFS=","
mystring="${myarray[*]}"
declare -p mystring
# => declare -- mystring="one,two,three,four"
join() {
local IFS=$1
shift
local elements=("$@")
echo "${elements[*]}"
}
join ":" "${myarray[@]}" # note, the "@" index
# => "one:two:three:four"
Ha az IFS-t a függvényen belül lokalizáljuk, nem kell elmentenünk a régi értékét, és visszaállítanunk az előző értékére a globális scope-ban.
Finomításként a speciális "$*" paraméter idézőjelben ugyanezt a funkciót nyújtja, így nem kell elmentenünk a függvény argumentumainak másolatát:
join() {
local IFS=$1
shift
echo "$*"
}
(IFS=","; echo "${myarray[*]}")
A zárójelek egy alshellt (az aktuális shell másolatát) hoznak létre. Amikor a zárójelek közötti parancsok befejeződnek, az alshell kilép, és a megváltozott IFS változó eltűnik.
Figyelem: ez nem fog működni: IFS="," echo "${myarray[*]}", mert a paraméterkiterjesztés előbb történik meg, mielőtt a shell alkalmazná a módosított IFS változót az echo parancsra.
Talán már láttad a "${variable:offset:length}" paraméterkiterjesztést, amely a változó értékének egy részstringjévé bővül.
Ugyanezt megtehetjük tömbökkel is, hogy a tömb egy szeletét kapjuk meg.
myarray=(one two three four)
subarray=("${myarray[@]:0:2}")
declare -p subarray
# => declare -a subarray=([0]="one" [1]="two")
subarray=("${myarray[@]:1:3}")
declare -p subarray
# => declare -a subarray=([0]="two" [1]="three" [2]="four")
A hossz rész elhagyása azt jelenti, hogy „a kezdőponttól a tömb végéig”:
subarray=("${myarray[@]:2}")
declare -p subarray
# => declare -a subarray=([0]="three" [1]="four")
Ez nem olyan egyszerű, mint más nyelvekben, amiket esetleg ismersz. Két fő módszer van arra, hogy egy tömböt átadjunk egy függvénynek.
Az első módszernél a tömb összes értékét átadod, és a függvényben egy lokális tömbbe gyűjtöd őket.
myfunc() {
local array_copy=("$@")
# do stuff with array_copy
declare -p array_copy
}
array_original=(11 22 33 44)
myfunc "${array_original[@]}"
A függvény tömbje az értékek másolatát tartalmazza. A függvényben a tömbön végzett módosítások nem jelennek meg a külső scope-ban.
Ez a módszer jobban hasonlít a „referencia szerinti átadás” lehetőségéhez, amit más nyelvekből ismerhetsz. A tömb nevét adod át stringként. A függvény létrehoz egy lokális változót a „nameref” attribútummal. Ez a lokális tömb és a globális tömb (amelynek a nevét átadtuk) ugyanaz a tömb.
myfunc() {
# note the `-n` option
local -n local_array=$1
# do stuff with local_array
for i in "${!local_array[@]}"; do
printf '%d => %s\n' "$i" "${local_array[i]}"
end
# we can mutate it
local_array+=(55 66 77)
}
array_original=(11 22 33 44)
myfunc "array_original"
# show the mutated array
declare -p array_original
# => declare -a array_original=([0]="11" [1]="22" [2]="33" [3]="44" [4]="55" [5]="66" [6]="77")
A nameref asszociatív tömbökkel és „skalár” változókkal (amelyek stringértéket tartalmaznak) is működik.
A függvényen belül a declare -p local_array nem túl hasznos.
Csak ennyit ír ki: declare -n local_array="array_original".
A tömb részletes adatait úgy kapod meg, ha megvizsgálod az átadott tömb nevét: declare -p "$1"
Ügyelj rá, hogy a lokális tömb neve térjen el az átadott tömb nevétől. A kód ettől még működik, de „körkörös névre hivatkozás” figyelmeztetéseket ír ki, például ilyeneket:
myfunc() {
local -n a=$1
local IFS=,
echo "${a[*]}"
}
# same name as the function's local variable
a=(one two three)
myfunc a
bash: local: warning: a: circular name reference
bash: warning: a: circular name reference
bash: warning: a: circular name reference
bash: warning: a: circular name reference
one,two,three
Azokban a shellekben, amelyek csak a POSIX szabványnak próbálnak megfelelni (például az ash és a dash), nincsenek tömbök.
A legközelebbi megoldás a pozicionális paraméterek használata.
$1, $2 stb."$@" kifejezéssel az egyes elemekre bonthatók"$*" kifejezéssel egyetlen stringgé fűzhetők össze$# adja megA set paranccsal rendelhetsz nekik értékeket:
set -- one two three
set -- "$@" four
for item in "$@"; do
echo "do something with $item"
done
Ha a célod „hordozható” shell szkriptek írása, akkor a pozicionális paramétereket használod majd egy értékekből álló „lista” tárolására.