Erweiterte Linux -Unterschalen mit Beispielen

Erweiterte Linux -Unterschalen mit Beispielen

Wenn Sie unsere vorherigen Linux -Unterschalen für Anfänger mit Beispielen mit Beispielen lesen oder bereits mit Unterschalen erlebt werden, wissen Sie, dass Unterschalen eine leistungsstarke Möglichkeit sind, Bash -Befehle inline und kontextsensitiv zu manipulieren, und auf kontextsensitive Weise.

In diesem Tutorial lernen Sie:

  • So erstellen Sie fortgeschrittenere Subshell -Befehle
  • Wo Sie fortgeschrittenere Unterschalen in Ihrem eigenen Code einsetzen können
  • Beispiele für fortgeschrittenere Subshell -Befehle
Erweiterte Linux -Unterschalen mit Beispielen

Softwareanforderungen und Konventionen verwendet

Softwareanforderungen und Linux -Befehlszeilenkonventionen
Kategorie Anforderungen, Konventionen oder Softwareversion verwendet
System Linux-Verteilungsunabhängige
Software BASH -Befehlszeile, Linux -basiertes System
Andere Jedes Dienstprogramm, das standardmäßig nicht in der Bash -Shell enthalten ist sudo apt-Get Installieren Sie den Dienstprogramm (oder yum anstelle von APT-Get)
Konventionen # - Erfordert, dass Linux -Commands mit Root -Berechtigungen entweder direkt als Stammbenutzer oder mithilfe von verwendet werden sudo Befehl
$-erfordert, dass Linux-Commands als regulärer nicht privilegierter Benutzer ausgeführt werden

Beispiel 1: Dateien zählen

$ if [$ (ls [a -z]* 2>/dev/null | wc -l) -Gt 0]; dann Echo "fand ein oder mehrere Ereignisse von [a-z]* Dateien!"; fi 


Hier haben wir eine Wenn Aussage mit dem ersten Vergleichswert eine Unterschale. Dies funktioniert gut und bietet viel Flexibilität, wenn es um das Schreiben geht Wenn Aussagen. Es ist anders als das binäre (wahr oder falsche) Operation von zum Beispiel a Wenn Grep -q 'Search_term' ./docfile.txt Stellungnahme. Vielmehr wird es bewertet an sich als Standardvergleich (gegen den größeren Null angepasst -GT 0 Klausel).

Die Subshell versucht zu den genannten Verzeichnislistendateien [a-z]*, ich.e. Dateien beginnen mit mindestens einem Buchstaben in der a-z Bereich, gefolgt von einem nachfolgenden Charakter. Es ist fehlersicher durch Hinzufügen 2>/dev/null - ich.e. Jeder angezeigte Fehler (auf Stderr - die Standardfehlerausgabe, die durch die bestimmt ist 2) wird umgeleitet > Zu /dev/null - ich.e. das Linux null -Gerät - und somit ignoriert.

Schließlich übergeben wir den LS -Eingang an an WC -l die für uns zählen, wie viele Zeilen (oder in diesem Fall Dateien) gesehen wurden. Wenn das Ergebnis mehr als 0 war, wird die informative Notiz angezeigt.

Beachten Sie, wie der Kontext, in dem die Unterschale arbeitet. Erstens arbeitet die Unterschale in diesem Fall im aktuellen Arbeitsverzeichnis (i.e. $ Pwd) Das ist insbesondere der Standard ich.e. Subschalen starten standardmäßig mit ihrer eigenen Umgebung PWD Setzen Sie auf das aktuelle Arbeitsverzeichnis. Zweitens arbeitet die Unterschale im Kontext eines Wenn Stellungnahme.

Dieser Befehl erzeugt keine Ausgabe, da er in einem leeren Verzeichnis ausgeführt wird. Beachten Sie jedoch, dass die Tatsache, dass keine Ausgabe generiert wird, auch bedeutet, dass unsere Fehlerunterdrückung funktioniert. Überprüfen wir das:

$ if [$ (ls [a -z]* | wc -l) -Gt 0]; dann Echo "fand ein oder mehrere Ereignisse von [a-z]* Dateien!"; fi ls: Kann nicht zugreifen '[a-z]*': Keine solche Datei oder Verzeichnis 

Wir können sehen, wie das Entfernen der Fehlerunterdrückung im früheren Beispiel funktioniert hat. Lassen Sie uns als nächstes eine Datei erstellen und sehen, wie unser Einzeiler ausgeführt wird:

$ touch a $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -Gt 0]; dann Echo "fand ein oder mehrere Ereignisse von [a-z]* Dateien!"; fi fand ein oder mehrere Vorkommen von [a-z]* Dateien! 


Großartig, es sieht so aus, als ob unser One-Liner-Skript gut funktioniert. Fügen wir als nächstes eine sekundäre Datei hinzu und prüfen wir, ob wir die Nachricht verbessern können

$ touch b $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -Gt 0]; dann Echo "fand ein oder mehrere Ereignisse von [a-z]* Dateien!"; fi fand ein oder mehrere Vorkommen von [a-z]* Dateien! $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -Gt 0]; dann echo "fand genau $ (ls [a-z]* 2>/dev/null | wc -l) Vorkommen von [a-z]* Dateien!"; fi fand genau 2 Vorkommen von [a-z]* Dateien! 

Hier sehen wir, dass das Hinzufügen einer zweiten Datei (von Berührung b) macht keinen Unterschied (wie in der ersten zu sehen ist Wenn Befehl), es sei denn, wir ändern die Ausgabe, um tatsächlich zu melden.

Dies ist jedoch nicht optimal codiert. In diesem Fall erfordern zwei Unterschalen Ausführung (die Kosten für eine Erstellung von Unterschalen sind sehr minimal. Wenn Sie jedoch viele Unterschalen in hoher Häufigkeit erzeugen, sind die Kosten wichtig), und die direkte Auflistung wird zweimal angefordert (zusätzliche E/A und zusätzliche E/A - Verlangsamen Sie unseren Code auf die Geschwindigkeit des E/A -Subsystems und die Art der verwendeten Festplatte). Lassen Sie uns dies in eine Variable stellen:

$ Count = "$ (ls [a -z]* 2>/dev/null | wc -l)"; if [$ count -Gt 0]; dann echo "fand genau $ count Vorkommen von [a-z]* Dateien!"; fi fand genau 2 Vorkommen von [a-z]* Dateien! 

Großartig. Dies ist optimalerer Code. Eine einzelne Unterschale wird verwendet und das Ergebnis wird in einer Variablen gespeichert, die dann zweimal verwendet wird, und es ist nur ein einzelnes Festplattenverzeichnis -Abruf erforderlich. Beachten Sie auch, dass diese Lösung möglicherweise thread-sicher ist.

Zum Beispiel in der Wenn Anweisung mit zwei Unterschalen, wenn in der Zeit zwischen der Ausführung dieser Unterschalen eine dritte Datei erstellt wurde, kann das Ergebnis so aussehen: Fanden genau 3 Ereignisse von [a-z]* Dateien! während der erste Wenn Aussage (unter Verwendung der ersten Unterschale) wirklich qualifiziert auf Wenn 2 -GT 0 - ich.e. 2. In diesem Fall würde es kaum einen Unterschied machen, aber Sie können sehen, wie es bei einigen Codierungen sehr wichtig werden kann.

Beispiel 2: Unterschalen zur Berechnung

$ touch z $ echo $ [$ (Datum + %S) - $ (STAT -C %Z ./z)] 1 $ echo $ [$ (Datum + %s) - $ (STAT -C %Z ./z)] 5 

Hier haben wir eine Datei erstellt, nämlich z, und fand anschließend das Alter der Datei in Sekunden lang mit dem zweiten Befehl heraus. Ein paar Sekunden später haben wir den Befehl erneut ausgeführt und können sehen, dass die Datei jetzt 5 Sekunden alt ist.

Der Datum +%s Der Befehl gibt uns die aktuelle Zeit in Sekunden seit Epoch (1970-01-01 UTC) und STAT -C %Z gibt uns die Sekunden seit der Epoche für die zuvor erstellte Datei, die hier erstellt wurde und jetzt hier verwiesen wird ./z, Alles, was wir anschließend tun müssen, ist, diese beiden voneinander zu subtrahieren. Wir platzieren die Datum +%s Erstens, da dies die höchste Zahl (die aktuelle Zeit) ist und somit den Versatz in Sekunden korrekt berechnen.

Der -C Option zu Stat Zeigt einfach an, dass wir in diesem Fall eine bestimmte Ausgangsformatierung wünschen %Z, oder mit anderen Worten die Zeit seit der Epoche. Für Datum Die Syntax für die gleiche Idee ist +%S, Obwohl in Verbindung mit der aktuellen Zeit und nicht mit einer bestimmten Datei zusammenhängt.

Beispiel 3: Unterschalen in SED und anderen Werkzeugen

$ echo '0'> a $ sed -i "S | 0 | $ (whoami) |" ./eine $ cat a roel 


Wie Sie sehen können, können wir in fast jedem Befehl, den wir in der Befehlszeile ausführen, eine Unterschale verwenden.

In diesem Fall erstellen wir eine Datei A mit als Inhalt 0 und anschließend inline die ersetzen die 0 Zu $ (whoami) Was, wenn die Unterschale ausgeführt wird, als der Befehl analysiert wird, ersetzt den Benutzernamen Roel. Achten Sie darauf, keine einzelnen Zitate zu verwenden, da dies die Unterschale inaktiv macht, da die Zeichenfolge als wörtlicher Text interpretiert wird:

$ echo '0'> a $ sed -i 's | 0 | $ (whoami) |' ./eine $ cat a $ (whoami) 

Beachten Sie hier, dass die sed Aktivierte Syntax (S | 0 |… |) funktioniert immer noch richtig (!), während die Bash -Subshell -Funktionalität $ () nicht!

Beispiel 4: Verwenden von Eval und A for Loop

$ Loops = 3 $ Echo 1… $ Loops 1… 3 $ eval echo 1… $ Loops 1 2 3 $ für i in $ (echo 1… $ Loops); echo "$ i"; Done 1… 3 $ für i in $ (eval echo 1… $ Loops); echo "$ i"; fertig 1 2 3 

In diesem Beispiel nicht die optimale Möglichkeit, eine einfache Durchführung zu erbringen für Schleife zeigt uns einige Möglichkeiten, Subschalen auch in Loops zu integrieren. Wir benutzen das bewerten Aussage, um die zu verarbeiten 1… 3 Text in 1 2 3, der dann direkt in den verwendet werden kann für Schleife Wiederholungsklausel.

Manchmal ist die Verwendung von Unterschalen und die Bereitstellung von Informationen in einer Line-In-Kontext durch Unterschalen nicht immer selbstverständlich und erfordern möglicherweise einige Tests, Optimierungen und Feinabstimmungen, bevor die Unterschalen wie erwartet ausgeführt werden. Dies ist normal und im Einklang mit der normalen Bash -Codierung.

Abschluss

In diesem Artikel haben wir einige detailliertere und erweiterte Beispiele für die Verwendung von Unterschalen in Bash untersucht. Mit der Kraft der Unterschalen können Sie die meisten Ein-Liner-Skripte in viel leistungsfähigere Versionen davon umwandeln, ganz zu schweigen von der Möglichkeit, sie in Ihren Skripten zu verwenden. Wenn Sie mit der Erkundung von Unterschalen beginnen und einige nette Möglichkeiten finden, sie zu verwenden, posten Sie sie unten in den Kommentaren!

Genießen!

Verwandte Linux -Tutorials:

  • Dinge zu installieren auf Ubuntu 20.04
  • Dinge zu tun nach der Installation Ubuntu 20.04 fokale Fossa Linux
  • Linux -Unterschalen für Anfänger mit Beispielen
  • Eine Einführung in Linux -Automatisierung, Tools und Techniken
  • So verwenden Sie Bash -Unterschalen im Inneren, wenn Anweisungen
  • Dinge zu tun nach der Installation Ubuntu 22.04 Jammy Quallen…
  • Linux -Befehle: Top 20 wichtigste Befehle, die Sie benötigen, um…
  • Grundlegende Linux -Befehle
  • Linux -Download
  • Installieren Sie Arch Linux in VMware Workstation