Πί

Πίνακες σε Bash

{one: "1 άσκηση", other: "%{count} ασκήσεις"}

Σχετικά με την έννοια Πίνακες

Το Bash παρέχει δύο τύπους παραμέτρων: "βαθμωτές" τιμές και πίνακες. Μια βαθμωτή τιμή μπορεί να είναι μια συμβολοσειρά ή ένας αριθμός· αντιπροσωπεύει ένα μόνο "πράγμα".

Τις περισσότερες φορές, οι βαθμωτές τιμές αρκούν για να περιέχουν τα δεδομένα σου. Μερικές φορές όμως χρειάζεται να αποθηκεύσεις μια λίστα από βαθμωτές τιμές. Σε αυτή την περίπτωση θα χρησιμοποιήσεις έναν πίνακα.

Υπάρχουν δύο είδη πινάκων:

  • Οι πίνακες με αριθμητικές θέσεις αντιστοιχίζουν ένα ακέραιο κλειδί σε μια τιμή συμβολοσειράς. (Σε άλλες γλώσσες μπορεί να το συναντήσεις ως "λίστα" ή "ακολουθία".)
  • Οι συσχετιστικοί πίνακες αντιστοιχίζουν ένα κλειδί συμβολοσειράς σε μια τιμή συμβολοσειράς. (Σε άλλες γλώσσες μπορεί να το συναντήσεις ως "αντιστοίχιση" ή "λεξικό".)

Τα πρώτα κεφάλαια αυτού του κειμένου καλύπτουν τους πίνακες με αριθμητικές θέσεις (στο εξής απλώς "πίνακες"). Λεπτομέρειες για τους συσχετιστικούς πίνακες εμφανίζονται στο τέλος.

Caution

Οι πίνακες του Bash μπορούν να αποθηκεύσουν μόνο βαθμωτές τιμές. Δεν υπάρχει η δυνατότητα δημιουργίας διδιάστατου πίνακα (πίνακα από πίνακες).

Δήλωση και αρχικοποίηση μιας μεταβλητής πίνακα

Μπορείς να αρχικοποιήσεις έναν πίνακα αναθέτοντας σε μια μεταβλητή μια λίστα στοιχείων μέσα σε παρενθέσεις (πιθανώς κενή).

myarray=("one" "two" "three")

Όπως συμβαίνει με κάθε ανάθεση μεταβλητής, δεν πρέπει να υπάρχουν κενά γύρω από το σύμβολο ίσον.

Πρόσεξε ότι δεν υπάρχουν κόμματά ανάμεσα στα στοιχεία· είναι μια λίστα από συμβολοσειρές χωρισμένες με κενά διαστήματα.

Στην πραγματικότητα, το πόσα κενά διαστήματα υπάρχουν μέσα στις παρενθέσεις είναι εντελώς αυθαίρετο. Οι αλλαγές γραμμής επιτρέπονται· χρησιμοποίησε όσες θέλεις για να βελτιώσεις την αναγνωσιμότητα.

myarray=(
    "first element"
    "second element"
    "this is the last element"
)

Αναθέτοντας μια λίστα συμβολοσειρών σε μια μεταβλητή πίνακα με αυτόν τον τρόπο, η πρώτη συμβολοσειρά αποθηκεύεται στη θέση μηδέν, η επόμενη στη θέση ένα, η επόμενη στη θέση δύο και ούτω καθεξής.

Μπορείς να αρχικοποιήσεις έναν "αραιό πίνακα" ορίζοντας τις θέσεις που χρειάζεσαι.

raindrops=([3]="Pling" [5]="Plang" [7]="Plong")
Note

Για να το επαναλάβουμε: οι θέσεις των πινάκων ξεκινούν από το μηδέν. Αυτό το απόσπασμα κώδικα τυπώνει "true":

myarray=("one" "two" "three")
[[ "${myarray[0]}" == "one" ]] && echo true || echo false

Μπορείς να χρησιμοποιήσεις την εντολή declare (ή local μέσα σε μια συνάρτηση) για να ορίσεις ότι μια μεταβλητή θα περιέχει έναν πίνακα.

declare -a myarray

Είναι πιο ιδιωματικό να αναθέσεις απλώς μια λίστα σε παρενθέσεις (ίσως κενή) για να αρχικοποιήσεις τη μεταβλητή.

Πρόσβαση στα στοιχεία ενός πίνακα

Όπως είδες στο σημείωση παραπάνω, η σύνταξη για να έχεις πρόσβαση σε ένα στοιχείο πίνακα είναι ${myarray[$index]}. Η θέση δίνεται μέσα σε αγκύλες. Τα άγκιστρα είναι υποχρεωτικά.

Note

Για τους πίνακες με αριθμητικές θέσεις, η θέση είναι μια αριθμητική παράσταση. Το εγχειρίδιο του Bash αναφέρει:

Μέσα σε μια αριθμητική παράσταση, οι μεταβλητές του shell μπορούν επίσης να αναφέρονται με το όνομά τους, χωρίς τη σύνταξη επέκτασης παραμέτρων.

Αυτό σημαίνει ότι το $ δεν είναι απαραίτητο για την "απλή" επέκταση μεταβλητής. Μπορείς να έχεις πρόσβαση στα στοιχεία έτσι, που είναι λίγο πιο ευανάγνωστο:

i=5
echo "${myarray[i]}"
# ..............^

Αν η θέση που δίνεις δεν υπάρχει στον πίνακα, το αποτέλεσμα της επέκτασης είναι μια κενή συμβολοσειρά.

Ανάθεση σε έναν πίνακα

Για να αναθέσεις σε ένα συγκεκριμένο στοιχείο του πίνακα, χρησιμοποίησε αυτή τη σύνταξη:

myarray[10]="hello"

Για να προσθέσεις στοιχεία στο τέλος ενός πίνακα, χρησιμοποίησε τον τελεστή συνένωσης και ανάθεσης += και βάλε παρενθέσεις:

myarray+=("new element 1" "new element 2")

Επανάληψη πάνω σε έναν πίνακα

Συνήθως θα χρειαστεί να κάνεις επανάληψη πάνω στις τιμές ενός πίνακα. Χρησιμοποίησε έναν βρόχο for (που τον είδες στην ενότητα Επανάληψη):

myarray=("one" "two" "three")
for value in "${myarray[@]}"; do
    echo "$value"
done

Πρόσεξε την ειδική σύνταξη για την επέκταση του πίνακα: "${myarray[@]}" Αυτή η μορφή επέκτασης παραμέτρων αντικαθιστά τις τιμές του πίνακα ως ξεχωριστές λέξεις. Είναι κατά κάποιο τρόπο ισοδύναμη με:

for value in "${myarray[0]}" "${myarray[1]}" ... "${myarray[n]}"

Η μορφή "${myarray[@]}" λειτουργεί με αραιούς πίνακες, επεκτεινόμενη μόνο στις τιμές που έχουν οριστεί.

Αυτή η ειδική επέκταση, όπου ως θέση χρησιμοποιείται το σύμβολο @, είναι ειδική μόνο μέσα σε διπλά εισαγωγικά.

Άλλες ειδικές επεκτάσεις παραμέτρων

Ακολουθούν μερικά ακόμη κομμάτια ειδικής σύνταξης που τα χρειαζόμαστε για την επανάληψη πάνω σε έναν πίνακα. Περιγράφονται στο εγχειρίδιο, στην ενότητα Επέκταση παραμέτρων του shell.

Για να βρεις το μήκος ενός πίνακα, χρησιμοποίησε το ${#myarray[@]}, με ένα # πριν από το όνομα. Το "μήκος" ενός πίνακα είναι ο αριθμός των στοιχείων του.

Για να πάρεις τη λίστα με τις θέσεις ενός πίνακα, χρησιμοποίησε το "${!myarray[@]}", με ένα ! πριν από το όνομα και την επέκταση μέσα σε διπλά εισαγωγικά. Για τους πίνακες με αριθμητικές θέσεις, οι θέσεις επεκτείνονται σε αριθμητική σειρά.

Επανάληψη πάνω στις θέσεις ενός πίνακα

Μερικές φορές χρειάζεσαι τη θέση μαζί με την τιμή. Υπάρχουν δύο τρόποι να το κάνεις.

  1. Όταν ξέρεις ότι οι θέσεις σχηματίζουν μια αδιάκοπη ακολουθία, μπορείς να χρησιμοποιήσεις έναν αριθμητικό βρόχο for.

    for ((i = 0; i < ${#myarray[@]}; i++)); do
        echo "$i -> ${myarray[i]}"
    done
    

    Πρόσεξε τη σύνταξη ${#myarray[@]}, με τον χαρακτήρα # μπροστά από το όνομα του πίνακα. Επειδή οι πίνακες αριθμούν τις θέσεις τους ξεκινώντας από το μηδέν, η τελευταία θέση του πίνακα είναι κατά ένα μικρότερη από το μήκος του.

  2. Όταν ο πίνακας είναι αραιός, μπορείς να χρησιμοποιήσεις αυτή τη μορφή:

    for index in "${!raindrops[@]}"; do
        echo "$index -> ${raindrops[index]}"
    done
    

    Πρόσεξε τη σύνταξη ${!myarray[@]}, με τον χαρακτήρα ! μπροστά από το όνομα του πίνακα.

Έλεγχος του περιεχομένου ενός πίνακα

Αν θέλεις να δεις το περιεχόμενο ενός πίνακα, χρησιμοποίησε την εντολή declare με την επιλογή -p:

a=("the 'first' element"
   second
   third
   'the "last" element')
declare -p a

Αυτό εμφανίζει το περιεχόμενο με την κανονική σύνταξη εισαγωγικών του shell.

declare -a a=([0]="the 'first' element" [1]="second" [2]="third" [3]="the \"last\" element")

Συσχετιστικοί πίνακες

Για να το επαναλάβουμε, οι συσχετιστικοί πίνακες χρησιμοποιούν συμβολοσειρές ως θέσεις, όχι αριθμούς. Όλα όσα γράψαμε παραπάνω ισχύουν και για τους συσχετιστικούς πίνακες, με μικρές διαφορές. Γενικά, χρησιμοποιούμε τον όρο "κλειδί" και όχι "θέση": οι συσχετιστικοί πίνακες αντιστοιχίζουν κλειδιά σε τιμές.

Δήλωση ενός συσχετιστικού πίνακα

Σε αντίθεση με τους πίνακες, οι συσχετιστικοί πίνακες πρέπει να δηλώνονται. Χρησιμοποίησε την επιλογή -A της declare (ή της local μέσα σε μια συνάρτηση):

declare -A mymap

myfunc() {
    local -A my_local_map
    # ...
}

Αρχικοποίηση ενός συσχετιστικού πίνακα

Τα ζεύγη κλειδιού-τιμής ορίζονται μέσα στη λίστα με τις παρενθέσεις:

mymap=([first]=foo [second]=bar [third]=baz)
declare -p mymap

Αυτό εμφανίζει:

declare -A mymap=([second]="bar" [first]="foo" [third]="baz")
Note

Να θυμάσαι ότι οι συσχετιστικοί πίνακες δεν έχουν σειρά.

Η δήλωση και η αρχικοποίηση μπορούν να γίνουν σε μία γραμμή.

declare -A mymap=([first]=foo [second]=bar [third]=baz)

Στις πρόσφατες εκδόσεις του Bash, η αρχικοποίηση μπορεί να χρησιμοποιήσει μια λίστα (key value key value ...).

declare -A mymap=(first foo second bar third baz)

Πρόσβαση στις τιμές

Χρησιμοποιείται η ίδια σύνταξη όπως πριν για την πρόσβαση στα στοιχεία: ${mymap[$key]}.

Τα κλειδιά των συσχετιστικών πινάκων δεν αξιολογούνται σε αριθμητικό πλαίσιο. Απαιτείται η συνήθης σύνταξη επέκτασης παραμέτρων.

Ανάθεση σε έναν συσχετιστικό πίνακα

Η ανάθεση χρησιμοποιεί την ίδια σύνταξη όπως πριν:

mymap[$key]="$value"

Επανάληψη

Μπορείς να χρησιμοποιήσεις έναν βρόχο for value in "${mymap[@]}" για να κάνεις επανάληψη. Ωστόσο, συνήθως θέλεις και το κλειδί μαζί με την τιμή.

Χρησιμοποίησε τη σύνταξη "${!mymap[@]}" που είδαμε παραπάνω.

for key in "${!mymap[@]}"; do
    echo "$key -> ${mymap[$key]}"
done

Αυτό εμφανίζει

second -> bar
first -> foo
third -> baz

Για να το τονίσουμε ξανά, τα κλειδιά δεν έχουν καμία σειρά.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα