Σε ένα σενάριο Bash θα ήθελα να χωρίσω μια γραμμή σε κομμάτια και να τα αποθηκεύσω σε έναν πίνακα.
Η γραμμή:
Paris, France, Europe
Θα ήθελα να τα έχω σε έναν πίνακα όπως αυτός:
array[0] = Paris
array[1] = France
array[2] = Europe
Θα ήθελα να χρησιμοποιήσω απλό κώδικα, η ταχύτητα της εντολής δεν έχει σημασία. Πώς μπορώ να το κάνω;
IFS=', ' read -r -a array <<< "$string"
Σημειώστε ότι οι χαρακτήρες στο $IFS
αντιμετωπίζονται ξεχωριστά ως διαχωριστικά, έτσι ώστε σε αυτή την περίπτωση τα πεδία μπορούν να διαχωριστούν με είτε ένα κόμμα είτε ένα κενό και όχι με την ακολουθία των δύο χαρακτήρων. Ενδιαφέρον όμως παρουσιάζει το γεγονός ότι κενά πεδία δεν δημιουργούνται όταν στην είσοδο εμφανίζεται κόμμα-διάστημα επειδή το διάστημα αντιμετωπίζεται ειδικά.
Για να αποκτήσετε πρόσβαση σε ένα μεμονωμένο στοιχείο:
echo "${array[0]}"
Για να επαναλάβετε τα στοιχεία:
for element in "${array[@]}"
do
echo "$element"
done
Για να λάβετε τόσο το δείκτη όσο και την τιμή:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
Το τελευταίο παράδειγμα είναι χρήσιμο επειδή οι πίνακες Bash είναι αραιοί. Με άλλα λόγια, μπορείτε να διαγράψετε ένα στοιχείο ή να προσθέσετε ένα στοιχείο και τότε οι δείκτες δεν είναι συνεχόμενοι.
unset "array[1]"
array[42]=Earth
Για να λάβετε τον αριθμό των στοιχείων ενός πίνακα:
echo "${#array[@]}"
Όπως αναφέρθηκε παραπάνω, οι πίνακες μπορεί να είναι αραιοί, οπότε δεν θα πρέπει να χρησιμοποιήσετε το μήκος για να πάρετε το τελευταίο στοιχείο. Εδώ θα δείτε πώς μπορείτε να το κάνετε στο Bash 4.2 και μεταγενέστερα:
echo "${array[-1]}"
σε οποιαδήποτε έκδοση του Bash (από κάπου μετά την 2.05b):
echo "${array[@]: -1:1}"
Οι μεγαλύτερες αρνητικές μετατοπίσεις επιλέγουν πιο μακριά από το τέλος του πίνακα. Προσέξτε το κενό πριν από το σύμβολο μείον στην παλαιότερη μορφή. Είναι απαραίτητο.
Ακολουθεί ένας τρόπος χωρίς ρύθμιση 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
Η ιδέα είναι η χρήση αντικατάστασης συμβολοσειρών:
${string//substring/replacement}
για την αντικατάσταση όλων των ταυτοποιήσεων του $substring με λευκό διάστημα και στη συνέχεια τη χρήση του υποκατασταθέντος αλφαριθμητικού για την αρχικοποίηση ενός πίνακα:
(element1 element2 ... elementN)
Σημείωση: αυτή η απάντηση κάνει χρήση του τελεστή split+glob. Έτσι, για να αποτρέψετε την επέκταση ορισμένων χαρακτήρων (όπως *
) είναι καλή ιδέα να διακόψετε το globbing για αυτό το σενάριο.
Μερικές φορές μου συνέβη να μην λειτουργεί η μέθοδος που περιγράφεται στην αποδεκτή απάντηση, ειδικά αν το διαχωριστικό είναι ένα carriage return.<br>, Σε αυτές τις περιπτώσεις έλυσα με τον εξής τρόπο:
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