In een Bash script wil ik een regel in stukken splitsen en in een array opslaan.
De regel:
Paris, France, Europe
Ik zou ze graag in een array hebben zoals deze:
array[0] = Paris
array[1] = France
array[2] = Europe
Ik zou graag eenvoudige code gebruiken, de snelheid van het commando's doet er niet toe. Hoe kan ik dit doen?
IFS=', ' read -r -a array <<< "$string"
Merk op dat de tekens in $IFS
afzonderlijk worden behandeld als scheidingstekens, zodat in dit geval velden kunnen worden gescheiden door either een komma of een spatie in plaats van de opeenvolging van de twee tekens. Interessant is echter dat lege velden niet worden aangemaakt als er een komma-spatie in de invoer voorkomt, omdat de spatie speciaal wordt behandeld.
Om toegang te krijgen tot een individueel element:
echo "${array[0]}"
Om over de elementen te lopen:
for element in "${array[@]}"
do
echo "$element"
done
Om zowel de index als de waarde te krijgen:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
Het laatste voorbeeld is nuttig omdat Bash arrays sparse zijn. Met andere woorden, je kunt een element verwijderen of een element toevoegen en dan zijn de indices niet aaneengesloten.
unset "array[1]"
array[42]=Earth
Om het aantal elementen in een array te krijgen:
echo "${#array[@]}"
Zoals hierboven vermeld, kunnen arrays schaars zijn, dus moet je'niet de lengte gebruiken om het laatste element te krijgen. Hier's hoe je dat wel kunt in Bash 4.2 en later:
echo "${array[-1]}"
in elke versie van Bash (vanaf ergens na 2.05b):
echo "${array[@]: -1:1}"
Grotere negatieve offsets selecteren verder van het einde van de array. Let op de spatie voor het minteken in de oudere vorm. Die is verplicht.
Hier is een manier zonder IFS in te stellen:
string="1:2:3:4:5"
set -f # avoid globbing (expansion of *).
array=(${string//:/ })
for i in "${!array[@]}"
do
echo "$i=>${array[i]}"
done
Het idee is om string replacement te gebruiken:
${string//substring/replacement}
om alle overeenkomsten van $substring te vervangen door witruimte en dan de gesubstitueerde string te gebruiken om een array te initialiseren:
(element1 element2 ... elementN)
Opmerking: dit antwoord maakt gebruik van de split+glob operator. Dus, om expansie van sommige karakters (zoals *
) te voorkomen, is het een goed idee om globbing te pauzeren voor dit script.
Soms overkwam het mij dat de methode beschreven in het geaccepteerde antwoord niet'werkte, vooral als het scheidingsteken een carriage return is.
In die gevallen loste ik het op deze manier op:
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