I et Bash-skript vil jeg gjerne dele en linje i biter og lagre dem i en matrise.
Linjen:
Paris, France, Europe
Jeg vil gjerne ha dem i en matrise som dette:
array[0] = Paris
array[1] = France
array[2] = Europe
Jeg vil gjerne bruke enkel kode, kommandohastigheten spiller ingen rolle. Hvordan kan jeg gjøre det?
IFS=', ' read -r -a array <<< "$string"
Merk at tegnene i $IFS
behandles individuelt som skilletegn, slik at feltene i dette tilfellet kan skilles med enten et komma eller et mellomrom i stedet for sekvensen av de to tegnene. Det er imidlertid interessant å merke seg at det ikke opprettes tomme felter når komma og mellomrom forekommer i inndataene, fordi mellomrom behandles spesielt.
For å få tilgang til et individuelt element:
echo "${array[0]}"
For å iterere over elementene:
for element in "${array[@]}"
do
echo "$element"
done
For å få både indeksen og verdien:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
Det siste eksemplet er nyttig fordi Bash-matriser er sparsomme. Med andre ord kan du slette et element eller legge til et element, og da er indeksene ikke sammenhengende.
unset "array[1]"
array[42]=Earth
For å få antall elementer i en matrise:
echo "${#array[@]}"
Som nevnt ovenfor kan matriser være sparsomme, så du bør ikke bruke lengden for å få det siste elementet. Her er hvordan du kan i Bash 4.2 og senere:
echo "${array[-1]}"
i hvilken som helst versjon av Bash (fra et sted etter 2.05b):
echo "${array[@]: -1:1}"
Større negative forskyvninger velger lenger fra slutten av matrisen. Legg merke til mellomrommet før minustegnet i den eldre formen. Det er påkrevd.
Her er en måte uten å sette 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
Ideen er å bruke strengerstatning:
${string//substring/replacement}
for å erstatte alle treff av $substring med mellomrom og deretter bruke den erstattede strengen til å initialisere en matrise:
(element1 element2 ... elementN)
Merk: Dette svaret bruker split+glob-operatoren. For å forhindre utvidelse av enkelte tegn (for eksempel *
) er det derfor lurt å sette globbing på pause for dette skriptet.
Noen ganger skjedde det med meg at metoden beskrevet i det aksepterte svaret ikke fungerte, spesielt hvis separatoren er en vognretur; I disse tilfellene løste jeg på denne måten:
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