Die Grundlagen der Bash-Skripterstellung

Shell-Skripte werden in der UNIX-Welt häufig verwendet. Sie eignen sich hervorragend, um sich wiederholende Aufgaben zu beschleunigen und komplexe Ausführungslogiken zu vereinfachen. Sie können so einfach sein wie eine Reihe von Befehlen oder sie können komplexe Aufgaben orchestrieren. In diesem Lernprogramm erfahren Sie mehr über die Bash-Skriptsprache, indem Sie Schritt für Schritt ein Beispielskript schreiben.


Das Fizz-Buzz-Problem

Eine der besten Möglichkeiten, eine neue Sprache zu erlernen, ist ein Beispiel. Beginnen wir mit einem.

Das Fizz-Buzz-Problem ist sehr einfach. Es wurde berühmt, nachdem ein Programmierer namens Imran es als Interviewtest verwendet hatte. Es stellt sich heraus, dass 90-99,5% der Kandidaten für einen Programmierjob einfach nicht in der Lage sind, das einfachste Programm zu schreiben. Imran nahm dieses einfache Fizz-Buzz-Spiel und bat die Kandidaten, es zu lösen. Viele folgten dem Beispiel von Imran, und heute ist es eine der am häufigsten gestellten Fragen für einen Programmierjob. Wenn Sie einstellen und 90% der Kandidaten durchforsten möchten, ist dies ein großes Problem.

Hier sind die Regeln:

  • Nehmen Sie die Zahlen zwischen 1 und 100 und drucken Sie sie aus.
  • Wenn eine Zahl durch 3 teilbar ist, drucken Sie "Fizz" anstelle der Zahl.
  • Wenn es durch 5 teilbar ist, drucken Sie stattdessen "Buzz".
  • Wenn es durch 3 und 5 teilbar ist, drucken Sie "FizzBuzz"..

Das ist alles dazu. Ich bin mir sicher, dass die meisten von euch die zwei oder drei bereits visualisieren können ob Aussagen zu lösen. Lassen Sie uns dies mit der Skriptsprache Bash durcharbeiten.


Shebang

Ein Shebang bezieht sich auf die Kombination von Hash- und Ausrufezeichen: #!. Der Programmlader sucht in der ersten Zeile des Skripts nach einem Shebang und verwendet den darin angegebenen Interpreter. Ein Shebang besteht aus der folgenden Syntax: #!Interpreter [Parameter]. Der Interpreter ist das Programm, das zur Interpretation unserer Sprache verwendet wird. Für Bash-Scripting wäre das so / bin / bash. Wenn Sie beispielsweise ein Skript in PHP erstellen und in der Konsole ausführen möchten, möchten Sie dies wahrscheinlich verwenden / usr / bin / php (oder den Pfad zur ausführbaren PHP-Datei auf Ihrem Computer) als Interpreter.

#! / usr / bin / php  

Ja, das geht tatsächlich! Ist es nicht einfach Stellen Sie sicher, dass Ihre Datei zuerst ausführbar ist. Sobald Sie dies tun, gibt dieses Skript Ihre PHP-Informationen wie erwartet aus.

Spitze: Um sicherzustellen, dass Ihr Skript auf so vielen Systemen wie möglich funktioniert, können Sie verwenden / bin / env im Shebang. Als solche statt / bin / bash, Du könntest benutzen / bin / env bash, Dies funktioniert auf Systemen, auf denen sich die ausführbare bash-Datei nicht befindet /Behälter.


Text ausgeben

Die Ausgabe eines Skripts entspricht erwartungsgemäß dem, was von Ihrem Befehl ausgegeben wird. Wenn wir jedoch ausdrücklich etwas auf den Bildschirm schreiben möchten, können wir dies verwenden Echo.

#! / bin / bash echo "Hello World"

Beim Ausführen dieses Skripts wird "Hello World" in der Konsole gedruckt.

csaba @ csaba ~ $ ./helloWorld.sh Hallo Welt csaba @ csaba ~ $

Variablen einführen

Wie in jeder Programmiersprache können Sie beim Schreiben von Shellskripten Variablen verwenden.

#! / bin / bash message = "Hallo Welt" echo $ message

Dieser Code erzeugt genau die gleiche "Hello World" -Meldung. Um einer Variablen einen Wert zuzuweisen, geben Sie einfach ihren Namen ein - schließen Sie das Dollarzeichen vor der Variablen aus. Seien Sie auch vorsichtig mit Leerzeichen; Zwischen dem Variablennamen und dem Gleichheitszeichen dürfen keine Leerzeichen stehen. So message = "Hallo" anstatt message = "Hallo"

Wenn Sie eine Variable verwenden möchten, können Sie den Wert genauso wie wir in der Variablen verwenden Echo Befehl. Vorbereiten eines $ an den Namen der Variablen wird der Wert zurückgegeben.

Spitze: Semikolons sind für das Bash-Scripting nicht erforderlich. Sie können sie in den meisten Fällen verwenden, aber seien Sie vorsichtig: Sie haben möglicherweise eine andere Bedeutung als Sie erwarten.


Drucken der Zahlen zwischen 1 und 100

Um unser Demo-Projekt fortzusetzen, müssen wir alle Zahlen zwischen 1 und 100 durchlaufen. Dazu benötigen wir eine zum Schleife.

#! / bin / bash für die Nummer in 1… 100; Echo $ number done

In diesem Beispiel gibt es einige neue Dinge, die es zu beachten gilt - wobei übrigens alle Zahlen von 1 bis 100 einzeln gedruckt werden.

  • Das zum Syntax in Bash ist: für VARIABLE in RANGE; erledige den Befehl.
  • Die geschweiften Klammern verwandeln sich 1… 100 in einem Bereich in unserem Beispiel. Sie werden auch in anderen Zusammenhängen verwendet, die wir in Kürze überprüfen werden.
  • tun und zum sind eigentlich zwei getrennte Befehle. Wenn Sie zwei Befehle in einer Zeile platzieren möchten, müssen Sie sie irgendwie trennen. Eine Möglichkeit ist, Semikolon zu verwenden. Alternativ können Sie den Code auch ohne Semikolon durch Verschieben schreiben tun in die folgende Zeile.
#! / bin / bash für Nummer in 1… 100 echo $ number done

Die erste Entscheidung

Da wir nun wissen, wie alle Zahlen zwischen 1 und 100 gedruckt werden sollen, ist es an der Zeit, unsere erste Entscheidung zu treffen.

#! / bin / bash für die Nummer in 1… 100; tun, wenn [$ ((Nummer% 3)) -eq 0]; dann Echo "Fizz" sonst Echo $ Nummer fi getan

In diesem Beispiel wird "Fizz" für durch 3 teilbare Zahlen ausgegeben. Wieder müssen wir uns mit etwas neuer Syntax auseinandersetzen. Nehmen wir sie einzeln auf.

  • wenn… dann… sonst… fi - Dies ist die klassische Syntax für ein ob Aussage in Bash. Natürlich die sonst Teil ist optional - aber in diesem Fall für unsere Logik erforderlich.
  • wenn BEFEHL-RÜCKGABEWERT; dann… - ob wird ausgeführt, wenn der Rückgabewert des Befehls Null ist. Ja, die Logik in Bash basiert auf Null, was bedeutet, dass Befehle, die erfolgreich ausgeführt werden, mit einem Code von 0 beendet werden. Wenn etwas schief geht, wird dagegen eine positive Ganzzahl zurückgegeben. Um die Dinge zu vereinfachen, wird alles andere als 0 berücksichtigt falsch.
  • Mathematische Ausdrücke in Bash werden durch doppelte Klammern angegeben. $ ((Nummer% 3)) gibt den verbleibenden Wert der Division der Variablen zurück, Nummer, bis 3. Bitte beachten Sie, dass wir nicht verwendet haben $ in der Klammer - nur vor ihnen.

Sie fragen sich vielleicht, wo der Befehl in unserem Beispiel steht. Gibt es nicht nur eine Klammer mit einem merkwürdigen Ausdruck darin? Nun, das stellt sich heraus [ ist eigentlich ein ausführbarer Befehl. Probieren Sie die folgenden Befehle in Ihrer Konsole aus, um damit herumzuspielen.

csaba @ csaba ~ $ welche [/ usr / bin / [csaba @ csaba ~ $ [0-eq 1] csaba @ csaba ~ $ echo $? 1 csaba @ csaba ~ $ [0-eq 0] csaba @ csaba ~ $ echo $? 0

Spitze: Der Exit-Wert eines Befehls wird immer in die Variable zurückgegeben, ? (Fragezeichen). Sie wird nach der Ausführung jedes neuen Befehls überschrieben.


Auf Buzz prüfen

Bis jetzt geht es uns gut. Wir haben "Fizz"; Lassen Sie uns jetzt den "Buzz" -Teil ausführen.

#! / bin / bash für die Nummer in 1… 100; tun, wenn [$ ((Nummer% 3)) -eq 0]; dann Echo "Fizz" elif [$ ((number% 5)) -eq 0]; dann echo "Buzz" sonst echo $ number fi fertig

Oben haben wir mit 5 eine weitere Bedingung für die Teilbarkeit eingeführt: die elif Aussage. Das bedeutet natürlich zu sonst wenn, und wird ausgeführt, wenn der folgende Befehl zurückgegeben wird wahr (oder 0). Wie Sie sehen können, sind die Bedingungsanweisungen darin enthalten [] werden normalerweise mit Hilfe von Parametern wie z -Gl, das steht für "gleich".

Für die Syntax, arg1 OP arg2, OP ist einer von -Gl, -ne, -Es ist, -le, -gt, oder -ge. Diese arithmetischen Binäroperatoren werden zurückgegeben wahr ob arg1 gleich, nicht gleich, kleiner als, kleiner oder gleich, größer als oder größer als oder gleich ist arg2, beziehungsweise.arg1 und arg2 kann positive oder negative ganze Zahlen sein. - Bash Manual

Wenn Sie versuchen, Zeichenfolgen zu vergleichen, können Sie die bekannten verwenden == Zeichen, oder sogar ein einzelnes Gleichheitszeichen reicht aus. != kehrt zurück wahr wenn die Saiten unterschiedlich sind.


Der Code ist jedoch nicht ganz richtig

Bisher läuft der Code, aber die Logik stimmt nicht. Wenn die Zahl sowohl durch 3 als auch durch 5 teilbar ist, wird unsere Logik nur "Fizz" wiedergeben. Lassen Sie uns unseren Code ändern, um die letzte Anforderung von FizzBuzz zu erfüllen.

#! / bin / bash für die Nummer in 1… 100; tun, wenn [$ ((Nummer% 3)) -eq 0]; dann Ausgabe = "Fizz" fi wenn [$ ((Anzahl% 5)) -eq 0]; dann output = "$ output Buzz" fi wenn [-z $ output]; dann echo $ number sonst echo $ ausgabe; fi fertig

Wieder mussten wir eine Handvoll Änderungen vornehmen. Am bemerkenswertesten ist die Einführung einer Variablen und gegebenenfalls die Verkettung von "Buzz". Strings in Bash werden normalerweise zwischen Anführungszeichen (") definiert. Es können auch einfache Anführungszeichen verwendet werden. Um die Verkettung zu vereinfachen, sind Doubles jedoch die bessere Wahl. Innerhalb dieser Anführungszeichen können Sie Variablen referenzieren: etwas text $ variable etwas anderes text" wird ersetzen $ variable mit seinem Inhalt. Wenn Sie Variablen mit Zeichenfolgen ohne Leerzeichen verketten möchten, können Sie den Namen der Variablen lieber in geschweifte Klammern setzen. In den meisten Fällen, wie zum Beispiel PHP, ist dies nicht unbedingt erforderlich, aber es ist sehr hilfreich, wenn es um die Lesbarkeit des Codes geht.

Spitze: Sie können leere Zeichenfolgen nicht vergleichen. Das würde einen fehlenden Parameter zurückgeben.

Weil die Argumente drinnen sind [] werden als Parameter behandelt, z "[", Sie müssen sich von einer leeren Zeichenfolge unterscheiden. Daher wird dieser Ausdruck, auch wenn er logisch ist, einen Fehler ausgeben: [$ output! = ""]. Deshalb haben wir verwendet [-z $ Ausgabe], die zurückkehrt wahr wenn der String eine Länge von Null hat.


Extraktionsmethode für den logischen Ausdruck

Eine Möglichkeit, unser Beispiel zu verbessern, besteht darin, den mathematischen Ausdruck aus den Funktionen in Funktionen zu extrahieren ob Aussagen wie folgt:

#! / bin / bash-Funktion isDivisibleBy return $ (($ 1% $ 2)) für Zahl in 1… 100; do wenn isDivisibleBy $ number 3; dann output = "Fizz" fi wenn isDivisibleBy $ number 5; dann output = "$ output Buzz" fi wenn [-z $ output]; dann echo $ number sonst echo $ ausgabe; fi fertig

Wir haben die Ausdrücke genommen, die den Rest mit Null verglichen, und sie in eine Funktion verschoben. Darüber hinaus haben wir den Vergleich mit Null aufgehoben, weil Null für uns wahr ist. Wir müssen nur den Wert aus dem mathematischen Ausdruck zurückgeben - sehr einfach!

Spitze: Die Definition einer Funktion muss vor dem Aufruf stehen.

In Bash können Sie eine Methode als definieren Funktion func_name befehle; . Optional gibt es eine zweite Syntax zum Deklarieren von Funktionen: func_name () befehle; . So können wir die Zeichenfolge löschen, Funktion und hinzufügen "() nach dem Namen Ich persönlich bevorzuge diese Option, wie im obigen Beispiel veranschaulicht. Es ist expliziter und ähnelt traditionellen Programmiersprachen.

Sie müssen die Parameter für eine Funktion in Bash nicht angeben. Das Senden von Parametern an eine Funktion erfolgt durch einfaches Aufzählen nach dem Funktionsaufruf, getrennt durch Leerzeichen. Setzen Sie beim Funktionsaufruf keine Kommas oder Klammern - es funktioniert nicht.

Empfangene Parameter werden den Variablen automatisch nach Nummer zugewiesen. Der erste Parameter geht an 1 US-Dollar, die zweite zu 2 $, und so weiter. Die spezielle Variable, $ 0 verweist auf den Dateinamen des aktuellen Skripts.

Lass uns mit Parametern spielen

#! / bin / bash function exampleFunc echo $ 1 echo $ 0 IFS = "X" echo "$ @" echo "$ *" beispielFunc "eins" "zwei" "drei"

Dieser Code erzeugt die folgende Ausgabe:

csaba @ csaba ~ $ ./parametersExamples.sh eins ./parametersExamples.sh eins zwei drei oneXtwoXthre

Analysieren wir die Quelle Zeile für Zeile.

  • Die letzte Zeile ist der Funktionsaufruf. Wir nennen es mit drei String-Parametern.
  • Die erste Zeile nach dem Shebang ist die Funktionsdefinition.
  • Die erste Zeile der Funktion gibt den ersten Parameter aus: "Eins". So weit so einfach.
  • Die zweite Zeile gibt den Dateinamen des aktuellen Skripts aus. Wieder sehr einfach.
  • Die dritte Zeile ändert das Standardzeichentrennzeichen in den Buchstaben "X". Standardmäßig ist dies "" (ein Leerzeichen). So weiß Bash, wie die Parameter getrennt werden.
  • Die vierte Zeile gibt eine spezielle Variable aus, $ @. Es stellt alle Parameter als ein Wort dar, genau wie im Funktionsaufruf angegeben.
  • Die letzte Zeile gibt eine weitere spezielle Variable aus, $ *. Es stellt alle Parameter einzeln dar und wird mit dem ersten Buchstaben der IFS-Variablen verkettet. Deshalb ist das Ergebnis oneXtwoXthre.

Strings aus Funktionen zurückgeben

Wie bereits erwähnt, können Funktionen in Bash nur Ganzzahlen zurückgeben. Als solches schreiben Gib "eine Zeichenfolge" zurück wäre ungültiger Code. In vielen Situationen benötigen Sie jedoch mehr als nur eine Null oder Eins. Wir können unser FizzBuzz-Beispiel so umgestalten, dass in der zum Anweisung, machen wir einfach einen Funktionsaufruf.

#! / bin / bash Funktion isDivisibleBy return $ (($ 1% $ 2)) Funktion fizzOrBuzz wenn isDivisibleBy $ 1 3; dann output = "Fizz" fi wenn isDivisibleBy $ 1 5; dann output = "$ output Buzz" fi wenn [-z $ output]; dann echo $ 1 sonst echo $ ausgabe; fi für die Nummer in 1… 100; fizzOrBuzz $ number erledigt

Nun, das ist der erste Schritt. Wir haben einfach den gesamten Code in eine Funktion extrahiert, genannt fizzOrBuzz, und dann ersetzt $ number mit 1 US-Dollar. Die gesamte Ausgabe erfolgt jedoch im fizzOrBuzz Funktion. Wir möchten aus dem ausgeben zum Schleife mit einem Echo Anweisung, damit wir jeder Zeile einen anderen String voranstellen können. Wir müssen das erfassen fizzOrBuzz Funktionsausgabe.

# […] Für Nummer in 1… 100; do echo "-'fizzOrBuzz $ number" "fizzBuzzer = $ (fizzOrBuzz $ number) echo" - $ fizzBuzzer "fertig

Wir haben unsere aktualisiert zum Nur ein wenig schleifen (keine anderen Änderungen). Wir haben jetzt alles zweimal auf zwei verschiedene Arten wiederholt, um die Unterschiede zwischen den beiden Lösungen für dasselbe Problem zu veranschaulichen.

Die erste Lösung zum Erfassen der Ausgabe einer Funktion oder eines anderen Befehls ist die Verwendung von Backticks. In 99% der Fälle wird dies gut funktionieren. Sie können eine Variable innerhalb von Backticks einfach anhand ihrer Namen referenzieren, wie wir es mit getan haben $ number. Die ersten Zeilen der Ausgabe sollten jetzt so aussehen:

csaba @ csaba ~ / Personal / Programmieren / NetTuts / Grundlagen von BASH-Skripterstellung / Quellen $ ./fizzBuzz.sh -1 -1 -2 -2 -Fizz -Fizz -4 -4 -Buzz -Buzz -Fizz -Fizz -7 -7

Wie Sie sehen, ist alles doppelt vorhanden. Gleiche Ausgabe.

Für die zweite Lösung haben wir uns entschieden, den Rückgabewert zuerst einer Variablen zuzuweisen. In dieser Aufgabe haben wir verwendet $ (), In diesem Fall fälscht das Skript das Skript, führt den Code aus und gibt seine Ausgabe zurück.


;, && und ||

Erinnerst du dich, dass wir hier und da Semikolon verwendet haben? Sie können verwendet werden, um mehrere Befehle auszuführen, die in derselben Zeile geschrieben sind. Wenn Sie sie durch Semikolons voneinander trennen, werden sie einfach ausgeführt.

Ein komplexerer Fall ist zu verwenden && zwischen zwei Befehlen. Ja, das ist ein logisches UND. Dies bedeutet, dass der zweite Befehl nur ausgeführt wird, wenn der erste Befehl zurückkehrt wahr (es endet mit 0). Das ist hilfreich. wir können das vereinfachen ob Anweisungen in diesen Abkürzungen:

#! / bin / bash-Funktion isDivisibleBy return $ (($ 1% $ 2)) Funktion fizzOrBuzz isDivisibleBy $ 1 3 && output = "Fizz" isDivisibleBy $ 1 5 && output = "$ output Buzz", wenn [-z $ ausgeben ]; dann echo $ 1 sonst echo $ ausgabe; fi für die Nummer in 1… 100; mache echo "-'fizzOrBuzz $ number" "fertig

Als unsere Funktion, isDivisibleBy gibt einen korrekten Rückgabewert zurück, den wir dann verwenden können && um die gewünschte Variable einzustellen. Was ist danach? && wird nur ausgeführt, wenn die Bedingung erfüllt ist wahr. In gleicher Weise können wir verwenden || (Double Pipe-Zeichen) als logisches ODER. Hier ist ein kurzes Beispiel.

csaba @ csaba ~ $ echo "bubu" || echo "bibi" bubu csaba @ csaba ~ $ echo false || echo "bibi" false csaba @ csaba ~ $

Abschließende Gedanken

Das macht es also für dieses Tutorial! Ich hoffe, dass Sie eine Handvoll neuer Tipps und Techniken für das Schreiben Ihrer eigenen Bash-Skripts erhalten haben. Vielen Dank für das Lesen und bleiben Sie dran für weiterführende Artikel zu diesem Thema.