Verwendung des Befehls sed unter Linux

Es mag verrückt klingen, aber der Linux- sedBefehl ist ein Texteditor ohne Schnittstelle. Sie können es über die Befehlszeile verwenden, um Text in Dateien und Streams zu bearbeiten. Wir zeigen Ihnen, wie Sie seine Kraft nutzen können.

Die Kraft von sed

Der sedBefehl ist ein bisschen wie Schach: Es dauert eine Stunde, um die Grundlagen zu lernen, und ein Leben lang, um sie zu beherrschen (oder zumindest viel Übung). Wir zeigen Ihnen eine Auswahl von Eröffnungsgambits in jeder der Hauptkategorien von sedFunktionen.

sedist ein Stream-Editor, der mit Pipeline-Eingaben oder Textdateien arbeitet. Es gibt jedoch keine interaktive Texteditor-Oberfläche. Sie geben vielmehr Anweisungen, die Sie befolgen müssen, wenn Sie den Text durcharbeiten. Dies alles funktioniert in Bash und anderen Befehlszeilen-Shells.

Mit sedkönnen Sie Folgendes tun:

  • Text auswählen
  • Ersatztext
  • Fügen Sie dem Text Zeilen hinzu
  • Zeilen aus dem Text löschen
  • Ändern (oder beibehalten) Sie eine Originaldatei

Wir haben unsere Beispiele so strukturiert, dass Konzepte eingeführt und demonstriert werden und nicht die knappsten (und am wenigsten zugänglichen) sedBefehle erstellt werden. Die Funktionen für Musterabgleich und Textauswahl von sed hängen jedoch stark von regulären Ausdrücken (regulären Ausdrücken) ab. Sie müssen mit diesen vertraut sein, um das Beste aus ihnen herauszuholen sed.

VERBINDUNG: Verwendung regulärer Ausdrücke (Regexes) unter Linux

Ein einfaches Beispiel

Zuerst werden wir echoText seddurch eine Pipe senden und sed einen Teil des Textes ersetzen. Dazu geben wir Folgendes ein:

echo howtogonk | sed 's / gonk / geek /'

Der echoBefehl sendet "howtogonk" an sedund unsere einfache Substitutionsregel (das "s" steht für Substitution) wird angewendet. sed Durchsucht den Eingabetext nach einem Vorkommen der ersten Zeichenfolge und ersetzt alle Übereinstimmungen durch die zweite.

Die Zeichenfolge "gonk" wird durch "geek" ersetzt und die neue Zeichenfolge wird im Terminalfenster gedruckt.

Substitutionen sind wahrscheinlich die häufigste Verwendung von sed. Bevor wir uns jedoch eingehender mit Substitutionen befassen können, müssen wir wissen, wie Text ausgewählt und abgeglichen wird.

Text auswählen

Für unsere Beispiele benötigen wir eine Textdatei. Wir werden einen verwenden, der eine Auswahl von Versen aus Samuel Taylor Coleridges epischem Gedicht "The Rime of the Ancient Mariner" enthält.

Wir geben Folgendes ein, um es uns anzusehen less:

weniger coleridge.txt

Um einige Zeilen aus der Datei auszuwählen, geben wir die Start- und Endzeilen des Bereichs an, den wir auswählen möchten. Eine einzelne Zahl wählt diese eine Zeile aus.

Um die Zeilen eins bis vier zu extrahieren, geben wir diesen Befehl ein:

sed -n '1,4p' coleridge.txt

Beachten Sie das Komma zwischen 1und 4. Das pbedeutet "übereinstimmende Zeilen drucken". Standardmäßig werden  sed alle Zeilen gedruckt. Wir würden den gesamten Text in der Datei mit den übereinstimmenden Zeilen sehen, die zweimal gedruckt wurden. Um dies zu verhindern, verwenden wir die -nOption (leise), um den nicht übereinstimmenden Text zu unterdrücken.

Wir ändern die Zeilennummern, damit wir einen anderen Vers auswählen können, wie unten gezeigt:

sed -n '6,9p' coleridge.txt

Wir können die -eOption (Ausdruck) verwenden, um mehrere Auswahlen zu treffen. Mit zwei Ausdrücken können wir zwei Verse auswählen, wie folgt:

sed -n -e '1,4p' -e '31, 34p 'coleridge.txt

Wenn wir die erste Zahl im zweiten Ausdruck reduzieren, können wir zwischen den beiden Versen ein Leerzeichen einfügen. Wir geben Folgendes ein:

sed -n -e '1,4p' -e '30, 34p 'coleridge.txt

Wir können auch eine Startzeile auswählen und anweisen sed , die Datei zu durchlaufen und jede fünfte Zeile alternative Zeilen zu drucken oder eine beliebige Anzahl von Zeilen zu überspringen. Der Befehl ähnelt dem oben verwendeten, um einen Bereich auszuwählen. Dieses Mal verwenden wir jedoch eine Tilde ( ~) anstelle eines Kommas, um die Zahlen zu trennen.

Die erste Zahl gibt die Startlinie an. Die zweite Zahl gibt an, sedwelche Zeilen nach der Startzeile angezeigt werden sollen. Die Zahl 2 bedeutet jede zweite Zeile, 3 bedeutet jede dritte Zeile und so weiter.

Wir geben Folgendes ein:

sed -n '1 ~ 2p' coleridge.txt

Sie werden nicht immer wissen, wo sich der gesuchte Text in der Datei befindet, was bedeutet, dass Zeilennummern nicht immer eine große Hilfe sind. Sie können jedoch auch sed Zeilen auswählen, die übereinstimmende Textmuster enthalten. Lassen Sie uns zum Beispiel alle Zeilen extrahieren, die mit "Und" beginnen.

Das caret ( ^) repräsentiert den Zeilenanfang. Wir werden unseren Suchbegriff in Schrägstriche ( /) einfügen . Nach "Und" wird ein Leerzeichen eingefügt, sodass Wörter wie "Android" nicht im Ergebnis enthalten sind.

Das Lesen von sedSkripten kann zunächst etwas schwierig sein. Das /p bedeutet "Drucken", genau wie in den oben verwendeten Befehlen. Im folgenden Befehl steht jedoch ein Schrägstrich davor:

sed -n '/ ^ und / p' coleridge.txt

Drei Zeilen, die mit „Und“ beginnen, werden aus der Datei extrahiert und für uns angezeigt.

Substitutionen vornehmen

In unserem ersten Beispiel haben wir Ihnen das folgende Grundformat für eine sedSubstitution gezeigt:

echo howtogonk | sed 's / gonk / geek /'

Das ssagt, dass sed dies eine Substitution ist. Die erste Zeichenfolge ist das Suchmuster, und die zweite Zeichenfolge ist der Text, durch den der übereinstimmende Text ersetzt werden soll. Natürlich steckt der Teufel wie bei allen Linux-Dingen im Detail.

Wir geben Folgendes ein, um alle Vorkommen von "Tag" in "Woche" zu ändern und dem Seefahrer und dem Albatros mehr Zeit zum Binden zu geben:

sed -n 's / Tag / Woche / p' coleridge.txt

In der ersten Zeile wird nur das zweite Vorkommen von "Tag" geändert. Dies liegt daran, dass sednach dem ersten Spiel pro Zeile angehalten wird. Wir müssen am Ende des Ausdrucks ein "g" hinzufügen, wie unten gezeigt, um eine globale Suche durchzuführen, damit alle Übereinstimmungen in jeder Zeile verarbeitet werden:

sed -n 's / Tag / Woche / gp' coleridge.txt

Dies entspricht drei von vier in der ersten Zeile. Da das erste Wort "Tag" ist und zwischen sedGroß- und Kleinschreibung unterschieden wird, wird diese Instanz nicht als "Tag" angesehen.

Wir geben Folgendes ein und fügen i dem Befehl am Ende des Ausdrucks ein hinzu, um die Groß- und Kleinschreibung nicht anzuzeigen:

sed -n 's / Tag / Woche / gip' coleridge.txt

Dies funktioniert, aber Sie möchten möglicherweise nicht immer die Groß- und Kleinschreibung für alles aktivieren. In diesen Fällen können Sie eine Regex-Gruppe verwenden, um musterspezifische Groß- und Kleinschreibung zu vermeiden.

Wenn wir beispielsweise Zeichen in eckige Klammern ( []) setzen, werden sie als "beliebige Zeichen aus dieser Liste von Zeichen" interpretiert.

Wir geben Folgendes ein und fügen "D" und "d" in die Gruppe ein, um sicherzustellen, dass es sowohl mit "Tag" als auch mit "Tag" übereinstimmt:

sed -ns / [Dd] ay / week / gp 'coleridge.txt

Wir können Ersetzungen auch auf Abschnitte der Datei beschränken. Nehmen wir an, unsere Datei enthält im ersten Vers seltsame Abstände. Wir können den folgenden bekannten Befehl verwenden, um den ersten Vers zu sehen:

sed -n '1,4p' coleridge.txt

Wir werden nach zwei Leerzeichen suchen und sie durch eines ersetzen. Wir werden dies global tun, damit die Aktion über die gesamte Linie wiederholt wird. Um klar zu sein, ist das Suchmuster Leerzeichen, Leerzeichen ( *) und die Ersetzungszeichenfolge ist ein einzelnes Leerzeichen. Das 1,4beschränkt die Ersetzung auf die ersten vier Zeilen der Datei.

All das fassen wir im folgenden Befehl zusammen:

sed -n '1,4 s / * / / gp' coleridge.txt

Das funktioniert gut! Das Suchmuster ist hier wichtig. Das Sternchen ( *) steht für null oder mehr des vorhergehenden Zeichens, bei dem es sich um ein Leerzeichen handelt. Daher sucht das Suchmuster nach Zeichenfolgen mit einem oder mehreren Leerzeichen.

Wenn wir eine Folge mehrerer Leerzeichen durch ein einzelnes Leerzeichen ersetzen, wird die Datei auf den regulären Abstand zurückgesetzt, wobei zwischen jedem Wort ein einzelnes Leerzeichen steht. In einigen Fällen wird dadurch auch ein einzelnes Leerzeichen durch ein einzelnes Leerzeichen ersetzt, dies hat jedoch keine nachteiligen Auswirkungen - wir erhalten trotzdem das gewünschte Ergebnis.

Wenn wir Folgendes eingeben und das Suchmuster auf ein einzelnes Leerzeichen reduzieren, werden Sie sofort erkennen, warum wir zwei Leerzeichen einfügen müssen:

sed -n '1,4 s / * / / gp' coleridge.txt

Da das Sternchen mit null oder mehr des vorhergehenden Zeichens übereinstimmt, wird jedes Zeichen, das kein Leerzeichen ist, als „Null-Leerzeichen“ angezeigt und die Ersetzung darauf angewendet.

Wenn wir jedoch zwei Leerzeichen in das Suchmuster aufnehmen,  sedmuss mindestens ein Leerzeichen gefunden werden, bevor die Ersetzung angewendet wird. Dies stellt sicher, dass Nicht-Leerzeichen unberührt bleiben.

Wir geben Folgendes mit dem zuvor verwendeten -e(Ausdruck) ein , mit dem wir zwei oder mehr Substitutionen gleichzeitig vornehmen können:

sed -n -e 's / Bewegung / Flattern / Gip' -e 's / Ozean / Rinne / Gip' coleridge.txt

Wir können das gleiche Ergebnis erzielen, wenn wir ein Semikolon ( ;) verwenden, um die beiden Ausdrücke wie folgt zu trennen:

sed -n 's / Bewegung / Flattern / Gip; s / Ozean / Rinne / Gip' coleridge.txt

Wenn wir im folgenden Befehl "Tag" gegen "Woche" tauschten, wurde auch die Instanz von "Tag" im Ausdruck "gut am Tag" getauscht:

sed -ns / [Dd] ay / week / gp 'coleridge.txt

Um dies zu verhindern, können wir nur Ersetzungen für Zeilen versuchen, die mit einem anderen Muster übereinstimmen. Wenn wir den Befehl so ändern, dass zu Beginn ein Suchmuster angezeigt wird, werden nur Zeilen in Betracht gezogen, die diesem Muster entsprechen.

Wir geben Folgendes ein, um unser passendes Muster zum Wort "nach" zu machen:

sed -n '/ after / s / [Dd] ay / week / gp' coleridge.txt

Das gibt uns die Antwort, die wir wollen.

Komplexere Substitutionen

Lassen Sie uns Coleridge eine Pause geben und seddamit Namen aus der etc/passwdDatei extrahieren .

Es gibt kürzere Möglichkeiten, dies zu tun (dazu später mehr), aber wir werden die längere Möglichkeit hier verwenden, um ein anderes Konzept zu demonstrieren. Jedes übereinstimmende Element in einem Suchmuster (als Unterausdrücke bezeichnet) kann nummeriert werden (maximal neun Elemente). Sie können diese Zahlen dann in Ihren  sedBefehlen verwenden, um auf bestimmte Unterausdrücke zu verweisen.

Sie müssen den Unterausdruck in Klammern [ ()] einfügen, damit dies funktioniert. Vor den Klammern muss außerdem ein Schrägstrich ( \) stehen, damit sie nicht als normales Zeichen behandelt werden.

Dazu geben Sie Folgendes ein:

sed 's / \ ([^:] * \). * / \ 1 /' / etc / passwd

Lassen Sie uns das zusammenfassen:

  • sed 's/: Der sedBefehl und der Beginn des Substitutionsausdrucks.
  • \(: Die öffnende Klammer [ (], die den Unterausdruck einschließt, gefolgt von einem Backslash ( \).
  • [^:]*: Der erste Unterausdruck des Suchbegriffs enthält eine Gruppe in eckigen Klammern. Das caret ( ^) bedeutet "nicht", wenn es in einer Gruppe verwendet wird. Eine Gruppe bedeutet, dass jedes Zeichen, das kein Doppelpunkt ( :) ist, als Übereinstimmung akzeptiert wird.
  • \): Die schließende Klammer [ )] mit einem vorangestellten Backslash ( \).
  • .*: Dieser zweite Suchunterausdruck bedeutet "ein beliebiges Zeichen und eine beliebige Anzahl von Zeichen".
  • /\1: Der Substitutionsteil des Ausdrucks enthält 1einen Backslash ( \). Dies stellt den Text dar, der dem ersten Unterausdruck entspricht.
  • /': Der schließende Schrägstrich ( /) und das einfache Anführungszeichen ( ') beenden den sedBefehl.

Dies alles bedeutet, dass wir nach Zeichenfolgen suchen, die keinen Doppelpunkt ( :) enthalten. Dies ist die erste Instanz von übereinstimmendem Text. Dann suchen wir in dieser Zeile nach etwas anderem, was die zweite Instanz von übereinstimmendem Text sein wird. Wir werden die gesamte Zeile durch den Text ersetzen, der dem ersten Unterausdruck entspricht.

Jede Zeile in der /etc/passwdDatei beginnt mit einem durch Doppelpunkte abgeschlossenen Benutzernamen. Wir passen alles bis zum ersten Doppelpunkt an und ersetzen dann die gesamte Zeile durch diesen Wert. Also haben wir die Benutzernamen isoliert.

Als nächstes setzen wir den zweiten Unterausdruck in Klammern [ ()], damit wir ihn auch nach Zahlen referenzieren können. Wir werden auch ersetzen \1 mit \2. Unser Befehl ersetzt nun die gesamte Zeile durch alles vom ersten Doppelpunkt ( :) bis zum Ende der Zeile.

Wir geben Folgendes ein:

sed 's / \ ([^:] * \) \ (. * \) / \ 2 /' / etc / passwd

Diese kleinen Änderungen kehren die Bedeutung des Befehls um und wir erhalten alles außer den Benutzernamen.

Schauen wir uns nun den schnellen und einfachen Weg an, dies zu tun.

Unser Suchbegriff reicht vom ersten Doppelpunkt ( :) bis zum Ende der Zeile. Da unser Ersetzungsausdruck leer ist ( //), ersetzen wir den übereinstimmenden Text nicht durch irgendetwas.

Also geben wir Folgendes ein und hacken alles vom ersten Doppelpunkt ( :) bis zum Ende der Zeile ab, wobei nur die Benutzernamen übrig bleiben:

sed 's /:.*// "/ etc / passwd

Schauen wir uns ein Beispiel an, in dem wir auf die erste und die zweite Übereinstimmung im selben Befehl verweisen.

Wir haben eine Datei mit Kommas ( ,), die Vor- und Nachnamen trennen. Wir wollen sie als "Nachname, Vorname" auflisten. Wir können  catwie unten gezeigt verwenden, um zu sehen, was in der Datei enthalten ist:

cat geeks.txt

Wie viele sedBefehle könnte dieser nächste zunächst undurchdringlich aussehen:

sed 's / ^ \ (. * \), \ (. * \) $ / \ 2, \ 1 / g' geeks.txt

Dies ist ein Substitutionsbefehl wie die anderen, die wir verwendet haben, und das Suchmuster ist recht einfach. Wir werden es unten aufschlüsseln:

  • sed 's/: Der normale Substitutionsbefehl.
  • ^: Da das Caret nicht zu einer Gruppe gehört ( []), bedeutet dies "Der Anfang der Zeile".
  • \(.*\),: Der erste Unterausdruck besteht aus einer beliebigen Anzahl von Zeichen. Es ist in Klammern [ ()] eingeschlossen, denen jeweils ein Backslash ( \) vorangestellt ist, damit wir ihn nach Nummer referenzieren können. Unser gesamtes Suchmuster wird bisher als Suche vom Zeilenanfang bis zum ersten Komma ( ,) nach einer beliebigen Anzahl von Zeichen übersetzt.
  • \(.*\):  Der nächste Unterausdruck ist (wieder) eine beliebige Anzahl von Zeichen. Es ist auch in Klammern [ ()] eingeschlossen, denen ein Backslash ( \) vorangestellt ist, damit wir den übereinstimmenden Text anhand der Nummer referenzieren können.
  • $/: Das Dollarzeichen ( $) stellt das Zeilenende dar und ermöglicht es unserer Suche, bis zum Zeilenende fortzufahren. Wir haben dies einfach verwendet, um das Dollarzeichen einzuführen. Wir brauchen es hier nicht wirklich, da das Sternchen ( *) in diesem Szenario am Ende der Zeile stehen würde. Der Schrägstrich ( /) vervollständigt den Suchmusterabschnitt.
  • \2,\1 /g': Da wir unsere beiden Unterausdrücke in Klammern gesetzt haben, können wir beide durch ihre Nummern referenzieren. Da wir die Reihenfolge umkehren möchten, geben wir sie als ein second-match,first-match. Vor den Zahlen muss ein Backslash ( \) stehen.
  • /g: Dadurch kann unser Befehl global in jeder Zeile arbeiten.
  • geeks.txt: Die Datei, an der wir arbeiten.

Sie können auch den Befehl Ausschneiden ( c) verwenden, um ganze Zeilen zu ersetzen, die Ihrem Suchmuster entsprechen. Wir geben Folgendes ein, um nach einer Zeile mit dem Wort "Hals" zu suchen und sie durch eine neue Textzeichenfolge zu ersetzen:

sed '/ neck / c Um mein Handgelenk war' coleridge.txt aufgereiht

Unsere neue Zeile erscheint jetzt am Ende unseres Auszuges.

Zeilen und Text einfügen

Wir können auch neue Zeilen und Text in unsere Datei einfügen. Um neue Zeilen nach übereinstimmenden einzufügen, verwenden wir den Befehl Anhängen ( a).

Hier ist die Datei, mit der wir arbeiten werden:

cat geeks.txt

Wir haben die Zeilen nummeriert, um das Verfolgen zu erleichtern.

Wir geben Folgendes ein, um nach Zeilen zu suchen, die das Wort "He" enthalten, und fügen eine neue Zeile darunter ein:

sed '/ He / a -> Eingefügt!' geeks.txt

Wir geben Folgendes ein und ifügen den Befehl Einfügen ( ) ein, um die neue Zeile über denjenigen einzufügen, die übereinstimmenden Text enthalten:

sed '/ He / i -> Eingefügt!' geeks.txt

Wir können das kaufmännische Und ( &) verwenden, das den ursprünglich übereinstimmenden Text darstellt, um einer übereinstimmenden Zeile neuen Text hinzuzufügen. \1 ,  \2usw. repräsentieren übereinstimmende Unterausdrücke.

Um dem Zeilenanfang Text hinzuzufügen, verwenden wir einen Ersetzungsbefehl, der mit allem in der Zeile übereinstimmt, kombiniert mit einer Ersetzungsklausel, die unseren neuen Text mit der ursprünglichen Zeile kombiniert.

Um all dies zu tun, geben wir Folgendes ein:

sed 's /.*/--> Eingefügt & /' geeks.txt

Wir geben Folgendes ein, einschließlich des GBefehls, mit dem zwischen jeder Zeile eine Leerzeile eingefügt wird:

sed 'G' geeks.txt

Wenn Sie zwei hinzufügen möchten oder mehrere Leerzeilen, können Sie verwenden G;GG;G;Gund so weiter.

Zeilen löschen

Der Befehl Löschen ( d) löscht Zeilen, die einem Suchmuster entsprechen, oder solche, die mit Zeilennummern oder Bereichen angegeben sind.

Um beispielsweise die dritte Zeile zu löschen, geben Sie Folgendes ein:

sed '3d' geeks.txt

Um den Zeilenbereich vier bis fünf zu löschen, geben Sie Folgendes ein:

sed '4,5d' geeks.txt

Um Zeilen außerhalb eines Bereichs zu löschen, verwenden wir ein Ausrufezeichen ( !), wie unten gezeigt:

sed '6,7! d' geeks.txt

Speichern Ihrer Änderungen

Bisher wurden alle unsere Ergebnisse im Terminalfenster gedruckt, aber wir haben sie noch nirgendwo gespeichert. Um diese dauerhaft zu machen, können Sie Ihre Änderungen entweder in die Originaldatei schreiben oder in eine neue umleiten.

Das Überschreiben Ihrer Originaldatei erfordert einige Vorsicht. Wenn Ihr sedBefehl falsch ist, können Sie einige Änderungen an der Originaldatei vornehmen, die schwer rückgängig zu machen sind.

Seit einiger Ruhe, sed kann eine Sicherungskopie der Originaldatei erstellen , bevor er seinen Befehl ausführt.

Mit der Option In-place ( -i) können Sie festlegen  sed, dass die Änderungen an der Originaldatei geschrieben werden sollen. Wenn Sie jedoch eine Dateierweiterung hinzufügen, sed wird die Originaldatei in einer neuen gesichert. Es hat den gleichen Namen wie die Originaldatei, jedoch eine neue Dateierweiterung.

Zur Demonstration suchen wir nach Zeilen, die das Wort „He“ enthalten, und löschen sie. Wir werden auch unsere Originaldatei mit der BAK-Erweiterung in einer neuen sichern.

Um all dies zu tun, geben wir Folgendes ein:

sed -i'.bak '' /^.*He.*$/d 'geeks.txt

Wir geben Folgendes ein, um sicherzustellen, dass unsere Sicherungsdatei unverändert bleibt:

cat geeks.txt.bak

Wir können auch Folgendes eingeben, um die Ausgabe in eine neue Datei umzuleiten und ein ähnliches Ergebnis zu erzielen:

sed -i'.bak '' /^.*He.*$/d 'geeks.txt> new_geeks.txt

Wir verwenden cat, um zu bestätigen, dass die Änderungen in die neue Datei geschrieben wurden, wie unten gezeigt:

cat new_geeks.txt

All das sediert

Wie Sie wahrscheinlich bemerkt haben, ist selbst diese schnelle Grundierung sedziemlich lang. Dieser Befehl hat viel zu bieten, und Sie können noch mehr damit tun.

Hoffentlich bieten diese Grundkonzepte eine solide Grundlage, auf der Sie aufbauen können, wenn Sie weiter lernen.