Μαθήματα Bash Scripting: Μεταβλητές – Συνθήκες – Συναρτήσεις


Μόλις δοκιμάσεις να γράψεις δυο εντολές σε ένα αρχείο κειμένου και το τρέξεις, δεν υπάρχει γυρισμός. Καλώς ήρθες στον μαγικό κόσμο του Bash Scripting και ετοιμάσου να μάθεις μεταβλητές, συνθήκες και συναρτήσεις

Εισαγωγή στο Bash Scripting

bash-scripting-metavlites-sunthikes-sunartiseis01

Ήδη γνωρίζεις ότι το τερματικό παρέχει ένα κέλυφος μεταξύ εσένα και τα ενδότερα του λειτουργικού συστήματος. Ο κέρσορας που αναβοσβήνει δεν είναι τίποτα άλλο, από την αγωνία του συστήματος που περιμένει την εντολή σου. Ότι του πεις θα το εκτελέσει, είτε είναι λάθος (συντακτικά) είτε σωστό. Δεν σε κρίνει…

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

Το σενάριο με άλλα λόγια είναι το Script και το κέλυφος είναι ο Bash. Ότι λοιπόν ξεκινάει με την παρακάτω μαγική λέξη:

#!/bin/bash

ξεκινάει ένα Bash Script και όταν, όπως θα μάθεις παρακάτω, του προσθέσεις μεταβλητές (variables), συνθήκες (conditions) και συναρτήσεις (functions) τότε έχεις γράψει κώδικα που θα εκτελείται μέσα από τερματικό (Δες παράδειγμα το Archon).

Μεταβλητές και Συνθήκες στο Bash Scripting

Στο άρθρο για το youtube-dl προστέθηκε μια παράγραφος με τίτλο «Δημιουργία μικρο-εφαρμογής για το youtube-dl» και έδειχνε τον τρόπο με τον οποίο μπορείς να την εκμεταλλευτείς φτιάχνοντας μια δική σου εντολή, επεκτείνοντας το.
Ας δούμε το script ξανά.

#!/bin/bash

clear
echo "Γίνεται λήψη της τελευταίας έκδοσης του youtube-dl"

sleep 2

sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl

sleep 1
echo ""
echo ""
read -rp " Δώσε μου το url link από το βίντεο η την playlist: " videolist

/usr/local/bin/youtube-dl --extract-audio --audio-format mp3 -o '%(title)s.%(ext)s' $videolist

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

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

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

Να ξεκαθαρίσουμε από τώρα κάτι. Πάρε τον χρόνο σου εφοδιάσου με καφέ και καθαρό μυαλό, γιατί δεν θα διαβάσεις απλώς ένα κείμενο. Θα το κάνεις ταυτόχρονα στον υπολογιστή σoυ.

Μια ταπεινή αρχή – Συνθήκη

Ανοίγω ένα τερματικό και γράφω

$ touch youtube-fetch2
$ chmod +x youtube-fetch2

Έχω λοιπόν ένα κενό εκτελέσιμο αρχείο.

Θα το ανοίξω με ένα επεξεργαστή κειμένου και θα προσθέτω κώδικα, ενώ στο τερματικό θα μπορώ πάντα να τον εκτελώ για έλεγχο με την εντολή ./youtube-fetch2.

Με τον αγαπημένο μου διορθωτή (ή απλά με ότι το ανοίξει κάνοντας διπλό κλικ) γράφω:

#!/bin/bash

if [ -z $1 ]; then
    echo "Δεν έδωσες παράμετρο θα ρωτήσω"
else
    echo "Μου έδωσες την παράμετρο ${1}"
fi

Είναι λίγο παράξενο στην σύνταξη, αλλά όσοι ξέρουν έστω και λίγο προγραμματισμό θα αναγνωρίσουν την σύνταξη μιας απόφασης που παίρνει το πρόγραμμα.

Αν το τρέξεις σαν ./youtube-fecth2 κάτι, τότε η πρώτη παράμετρος που έχει το μαγικό όνομα $1 δεν θα είναι κενή (zero, γιαυτό και το μαγικό -z) αλλά θα περιέχει την τιμή «κάτι». Άρα θα είναι λάθος η υπόθεση ότι είναι κενή. Άρα τι θα συμβεί; Δεν ξέρω. Δοκίμασε μόνος σου και τις δύο περιπτώσεις και βρες το μόνος σου. Το έκανες;

bash-scripting-metavlites-sunthikes-sunartiseis1

Προσέξτε κάτι πολύ σημαντικό. Τα κενά στην αρχή που διαχωρίζουν τις εντολές στις δύο περιπτώσεις. Το πρόγραμμα θα δουλέψει και χωρίς αυτά, αλλά μπορείς να καταλάβεις τι κάνει απο 3 μέτρα απόσταση; Και πολλά δύσκολα σφάλματα έχουν λυθεί κοιτώντας τον κώδικά από μακρυά. Ο κώδικάς έτσι μοιάζει όμορφος. Και ένας άσχημος κώδικάς είναι ένας κακός κώδικάς.

Μεταβλητή – Variable

Ωραία τώρα μπορούμε να φτιάξουμε κάτι που θα δουλέψει τουλάχιστον στην μια περίπτωση. Για την ακρίβεια δεν θα κατεβάσει κάτι, απλά θα γράψει τι θα κάνει, αλλά αυτό είναι καλύτερο και γρηγορότερο για την ώρα.

#!/bin/bash
if [ -z $1 ]; then
    echo "Δεν έδωσες παράμετρο θα ρωτήσω"
else
    echo "Μου έδωσες την παράμετρο ${1}"
videolist=$1
fi

echo "Κατεβάζω τώρα to $videolist"

Για να το δοκιμάσουμε τώρα. Δουλεύει σωστά; Ναι, αλλά τι έγινε; Προσθέσαμε στον κώδικά μια μεταβλητή με το όνομα videolist. Αν το γράψω σκέτο είναι το όνομα της, κάτι όχι τόσο χρήσιμο. Αλλά αυτό που θέλω είναι η τιμή της. Και αυτή είναι η $videolist ή διαφορετικά γραμμένο ${$videolist}.

bash-scripting-metavlites-sunthikes-sunartiseis2

Συναρτήσεις (functions) στο Bash Scripting

Λίγη βοήθεια από τον χρήστη

Μένει τώρα να κάνουμε το πρόγραμμα να ρωτάει τι πρέπει να κατέβει αν δεν δώσουμε κάτι. Ας κάνουμε μια πρώτη προσπάθεια:

#!/bin/bash

if [ -z $1 ]; then
    echo "Δεν έδωσες παράμετρο θα ρωτήσω"
    read -rp "Δώσε μου το url link από το βίντεο η την playlist: " videolist
else
    echo "Μου έδωσες την παράμετρο ${1}"
videolist=$1
fi

echo "Κατεβάζω τώρα to $videolist"

Συναρτήσεις

Ώρα για δοκιμή. Δουλεύει;

bash-scripting-metavlites-sunthikes-sunartiseis3

Ωραία. Ας το κάνουμε λίγο διαφορετικά τώρα:

#!/bin/bash

# Ρώτα τον χρήστη για την playlist ή το βίντεο
function get-playlist {
    echo "Δεν έδωσες παράμετρο θα ρωτήσω"
    read -rp "Δώσε μου το url link από το βίντεο η την playlist: " videolist
}

# Κατέβασε μια playlist ή το βίντεο
function download-playlist {
    echo "Κατεβάζω τώρα to $videolist"
}

### Αρχή
if [ -z $1 ]; then
    get-playlist
else
    echo "Μου έδωσες την παράμετρο ${1}"
videolist=$1
fi
download-playlist

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

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

Τι λες; Εξακολουθεί να δουλεύει; Δοκίμασε το

Μερεμέτια

Το φτιάξαμε ώστε να είναι πολύ εύκολο να το δούμε και να καταλάβουμε τι κάνει. Το κοιτάζω προσεχτικά, τα πάντα είναι μικρά και σωστά ονοματισμένα. Ένα λαμπάκι ανάβει στο μυαλό μου και το γράφω ως εξής:

#!/bin/bash
videolist=$1

# Ρώτα τον χρήστη για την playlist ή το βίντεο
function get-playlist {
    echo "Δεν έδωσες παράμετρο θα ρωτήσω"
    read -rp "Δώσε μου το url link από το βίντεο η την playlist: " videolist
}

# Κατέβασε μια playlist ή το βίντεο
function download-playlist {
    echo "Κατεβάζω τώρα to $videolist"
}

### Αρχή
if [ -z $1 ]; then
    get-playlist
fi
download-playlist

Δεν θα μπορούσα να το κάνω αυτό τόσο εύκολα αν δεν είχα σπάσει το πρόγραμμα προσεκτικά σε συναρτήσεις. Και δοκίμασε να δεις αν εξακολουθεί να δουλεύει. Μπορείς να καταλάβεις το γιατί;

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

#!/bin/bash

# Ρώτα τον χρήστη για την playlist ή το βίντεο
function get-playlist {
    echo "Δεν έδωσες παράμετρο θα ρωτήσω"
    read -rp "Δώσε μου το url link από το βίντεο η την playlist: " videolist
}

# Κατέβασε μια playlist ή το βίντεο
function download-playlist {
    echo "Κατεβάζω τώρα to $1"
}

### Αρχή
videolist=$1
if [ -z $1 ]; then
    get-playlist
fi
download-playlist ${videolist}

Μένει τώρα να το κάνουμε να κατεβάζει όντως κάτι από το δίκτυο γιατί μέχρι τώρα δεν κατεβάζει. Αυτό είναι τόσο εύκολο, που μπορείς να το κάνεις μόνος σου. Τι λες; Θα τα καταφέρεις; Μπορείς να προσθέσεις μια συνάρτηση που θα κατεβάζει το youtube-dl απο το δίκτυο;

Επίλογος

Αν το ξαναδιαβάσεις από την αρχή θα δεις πως δεν κάναμε πολλά πράγματα.

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

Που σταματάει κανείς; Όπου θέλει. Αν κάτι δουλέψει και είσαι ικανοποιημένος μια χαρά. Αλλά τα προγράμματα μπορεί να έχουν παράξενες ζωές. Αυτό το μικρό που έγραψες σήμερα μπορεί αύριο να γίνει κομμάτι μιας διανομής. Ποτέ δεν ξέρεις (δες π.χ. το uCareSystem)

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

Advertisements

6 thoughts on “Μαθήματα Bash Scripting: Μεταβλητές – Συνθήκες – Συναρτήσεις

  1. echo "Is your HardWare Platform 32bit or 64bit??"
    sleep 2
    echo "Let me see your Hardware Platform"
    sleep 2
    Mach = uname -m
    uname -i
    sleep 1
    if [${Mach} == 'x86_64'];
         then 
             echo "64"
         else 
             echo "32"
    exit 0
    fi

    Terminal output

    Let me see your Hardware Platform
    install.sh: 14: install.sh: Mach: not found
    x86_64
    install.sh: 20: [: missing ]
    32
    

    με δικαιωματα 770
    γιατι δεν το αναγνωριζει?

    1. Δεν έχει να κάνει με τα δικαιώματα και καλό είναι να μην τα πειράζεις. Το πρόβλημα εντοπίζεται σε 2 σημεία. Πρώτον το Mach = uname -m δεν αναγνωρίζεται γιατί έχεις κενό μετα το uname το οποίο για το τερματικό είναι χαρακτήρας οπότε σκαλώνει. Το δεύτερο σημείο είναι εκεί που καλείς με ‘if’ το μεταβλητή Mach είναι λανθασμένος. Μπορείς, όταν γράφεις bash shell να επισκεφτείς το shellcheck.net το οποίο όταν του βάλεις τον κώδικα θα σου λέει που χωλαίνει 😛 Εγώ πήγα και έβαλα τον κώδικά σου και μετά απο διορθώσεις ιδού το αποτέλεσμα που δουλεύει.

      #!/bin/bash
      echo "Is your HardWare Platform 32bit or 64bit??"
      sleep 2
      echo "Let me see your Hardware Platform"
      sleep 2
      Mach=$(uname -m)
      uname -i
      sleep 1
      if [ "$Mach" == "x86_64" ];
          then
              echo "64"
          else 
              echo "32"
      exit 0
      fi
      

Σου άρεσε το άρθρο; Πες την άποψή σου... έστω και Ανώνυμα:

Εισάγετε τα παρακάτω στοιχεία ή επιλέξτε ένα εικονίδιο για να συνδεθείτε:

Λογότυπο WordPress.com

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό WordPress.com. Αποσύνδεση / Αλλαγή )

Φωτογραφία Twitter

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Twitter. Αποσύνδεση / Αλλαγή )

Φωτογραφία Facebook

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Facebook. Αποσύνδεση / Αλλαγή )

Φωτογραφία Google+

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Google+. Αποσύνδεση / Αλλαγή )

Σύνδεση με %s