I et Bash-script vil jeg gerne opdele en linje i stykker og gemme dem i et array.
Linjen:
Paris, France, Europe
Jeg vil gerne have dem i et array som dette:
array[0] = Paris
array[1] = France
array[2] = Europe
Jeg vil gerne bruge simpel kode, kommandoen's hastighed er ligegyldig. Hvordan kan jeg gøre det?
IFS=', ' read -r -a array <<< "$string"
Bemærk, at tegnene i $IFS
behandles individuelt som separatorer, så i dette tilfælde kan felter adskilles med etter et komma eller et mellemrum i stedet for sekvensen af de to tegn. Det er dog interessant, at tomme felter ikke oprettes, når der forekommer komma-rum i input, fordi mellemrum behandles specielt.
For at få adgang til et enkelt element:
echo "${array[0]}"
For at iterere over elementerne:
for element in "${array[@]}"
do
echo "$element"
done
For at få både indekset og værdien:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
Det sidste eksempel er nyttigt, fordi Bash-arrays er sparsomme. Med andre ord kan du slette et element eller tilføje et element, og så er indeksene ikke sammenhængende.
unset "array[1]"
array[42]=Earth
Sådan får du antallet af elementer i et array:
echo "${#array[@]}"
Som nævnt ovenfor kan arrays være sparsomme, så du bør ikke bruge længden til at få fat i det sidste element. Her'er hvordan du kan i Bash 4.2 og senere:
echo "${array[-1]}"
i enhver version af Bash (fra et sted efter 2.05b):
echo "${array[@]: -1:1}"
Større negative forskydninger vælger længere væk fra arrayets ende. Bemærk mellemrummet før minustegnet i den ældre form. Det er påkrævet.
Her er en måde at gøre det på uden at indstille 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 at bruge strengudskiftning:
${string//substring/replacement}
til at erstatte alle match af $substring med hvidt mellemrum og derefter bruge den erstattede streng til at initialisere et array:
(element1 element2 ... elementN)
Bemærk: Dette svar gør brug af [split+glob-operatoren] (https://unix.stackexchange.com/q/108963/79743). For at forhindre ekspansion af visse tegn (såsom *
) er det således en god idé at sætte globbing på pause for dette script.
Nogle gange er det sket for mig, at den metode, der er beskrevet i det accepterede svar, ikke virkede, især hvis separatoren er en vogn retur.
I de tilfælde løste jeg det på denne måde:
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