W skrypcie Bash chciałbym podzielić linię na kawałki i przechowywać je w tablicy.
Linia:
Paris, France, Europe
Chciałbym mieć je w tablicy w ten sposób:
array[0] = Paris
array[1] = France
array[2] = Europe
Chciałbym użyć prostego kodu, prędkość komendy'nie ma znaczenia. Jak mogę to zrobić?
IFS=', ' read -r -a array <<< "$string"
Zauważ, że znaki w $IFS
traktowane są indywidualnie jako separatory, tak że w tym przypadku pola mogą być oddzielone albo przecinkiem albo spacją, a nie sekwencją tych dwóch znaków. Co ciekawe, puste pola nie są tworzone, gdy w danych wejściowych pojawi się przecinek, ponieważ spacja jest traktowana specjalnie.
Aby uzyskać dostęp do pojedynczego elementu:
echo "${array[0]}"
Aby wykonać iterację po elementach:
for element in "${array[@]}"
do
echo "$element"
done
Aby uzyskać zarówno indeks, jak i wartość:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
Ostatni przykład jest przydatny, ponieważ tablice Bash są rzadkie. Innymi słowy, możesz usunąć element lub dodać element, a wtedy indeksy nie są przyległe.
unset "array[1]"
array[42]=Earth
Aby uzyskać liczbę elementów w tablicy:
echo "${#array[@]}"
Jak wspomniano powyżej, tablice mogą być niekompletne, więc nie powinieneś używać długości do uzyskania ostatniego elementu. Oto jak można to zrobić w Bashu 4.2 i nowszych:
echo "${array[-1]}"
w dowolnej wersji Basha (od gdzieś po 2.05b):
echo "${array[@]: -1:1}"
Większe ujemne przesunięcia wybierają dalej od końca tablicy. Zwróć uwagę na spację przed znakiem minus w starszej formie. Jest ona wymagana.
Oto sposób bez ustawiania IFS:
string="1:2:3:4:5"
set -f # avoid globbing (expansion of *).
array=(${string//:/ })
for i in "${!array[@]}"
do
echo "$i=>${array[i]}"
done
Pomysł polega na użyciu zastępowania ciągów:
${string//substring/replacement}
aby zastąpić wszystkie dopasowania $substring białą spacją, a następnie użyć podstawionego łańcucha do zainicjalizowania tablicy:
(element1 element2 ... elementN)
Uwaga: ta odpowiedź korzysta z operatora split+glob. Tak więc, aby zapobiec ekspansji niektórych znaków (takich jak *
), dobrym pomysłem jest wstrzymanie globbingu dla tego skryptu.
Czasami zdarzało mi się, że metoda opisana w zaakceptowanej odpowiedzi nie działała, zwłaszcza jeśli separatorem był powrót karetki; W takich przypadkach rozwiązywałem to w ten sposób:
string='first line
second line
third line'
oldIFS="$IFS"
IFS='
'
IFS=${IFS:0:1} # this is useful to format your code with tabs
lines=( $string )
IFS="$oldIFS"
for line in "${lines[@]}"
do
echo "--> $line"
done