GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Erste Schritte mit dem SED-Befehl [Leitfaden für Anfänger]

Sed gehört seit Ende der 60er Jahre zum Unix-Standardwerkzeugkasten. Wie jeder Texteditor hilft es Ihnen, Textdateien zu ändern. Im Gegensatz zu den Texteditoren, die Sie möglicherweise bereits verwendet haben, ist dies jedoch ein nicht interaktiver.

Das bedeutet, dass Sie im Voraus die Transformationen angeben, die Sie auf eine Datei anwenden möchten, und das Tool diese Transformationen dann unbeaufsichtigt anwenden kann.

Die beste Beschreibung der Designziele des Tools stammt von Lee E. McMahon, dem Kernentwickler der ursprünglichen Implementierung, in seinem ursprünglichen Sed-Papier:

Sed ist ein nicht interaktiver Kontexteditor, der auf dem UNIX-Betriebssystem ausgeführt wird. Sed wurde entwickelt, um in drei Fällen besonders nützlich zu sein:

  1. Um Dateien zu bearbeiten, die für eine komfortable interaktive Bearbeitung zu groß sind;
  2. Um Dateien beliebiger Größe zu bearbeiten, wenn die Abfolge der Bearbeitungsbefehle zu kompliziert ist, um bequem im interaktiven Modus eingegeben zu werden.
  3. Um mehrere „globale“ Bearbeitungsfunktionen effizient in einem Durchgang durch die Eingabe auszuführen.

Die Zieldesigns (1) und (3) sind bei unserer modernen Hardware wahrscheinlich weniger relevant, aber das zweite bleibt gültig. Als persönliche Ergänzung würde ich sagen, dass sed besonders gut für sich wiederholende Aufgaben geeignet ist, z. B. wenn Sie dieselbe Transformation auf eine Reihe von Dateien anwenden möchten.

Lernen Sie grundlegende SED-Befehle mit diesen Beispielen

Um Ihnen einen Vorgeschmack auf die Leistungsfähigkeit von sed zu geben, werde ich den Fall einer Entwicklerin betrachten, die jeder Quelldatei in ihrem Projekt einen Lizenz-Header hinzufügen muss:

[email protected]:~$ head MIT.LICENSE *.sh
==> MIT.LICENSE <==
-----8<----------------------------------------------------------------
Copyright <YEAR> <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

==> script1.sh <==
#!/bin/bash

echo Hello, I\'m the first script

==> script2.sh <==
#!/bin/bash

cat << EOF
Hello, I'm the second script
EOF

Ich möchte nicht nur die Lizenzdatei über jedem Shell-Skript sehen, sondern auch das Jahr und den Copyright-Platzhalter durch ihren tatsächlichen Wert ersetzen. Das wird unser erster Anwendungsfall sein.

Hinweis:Wenn Sie selbst üben möchten, können Sie die Beispieldateien von meiner Website herunterladen. Vielleicht möchten Sie sich auch das Video ansehen, das diesen Artikel abschließt:

1. Text in SED ersetzen

In meiner Lizenzdatei möchte ich die Platzhalter und durch ihren tatsächlichen Wert ersetzen.

Das ist ein perfekt geeigneter Job für die sed Vertretung Befehl. Wahrscheinlich der nützlichste aller sed-Befehle:

[email protected]:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  | head -5
-----8<----------------------------------------------------------------
Copyright 2018 <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

Mit einer Pipe (| ) habe ich die Ausgabe des sed-Befehls an head weitergeleitet um hier nur die ersten fünf Zeilen anzuzeigen. Für unser heutiges spezifisches Thema ist der interessanteste Teil jedoch s/<YEAR>/2018/ Ausdruck.

Sed verarbeitet die Eingabedatei zeilenweise. In jeder Zeile wird der Ersatz (s ) ersetzt das erste Vorkommen des Textes zwischen den ersten beiden Schrägstrichen (/<YEAR>/ ) durch den Text zwischen den letzten beiden (/2018/ ). Stellen Sie sich das wie die Suchen-Ersetzen-Funktion vor, die Sie in einem GUI-Texteditor haben.

Erwähnenswert ist hier, dass die ursprüngliche MIT.LICENSE-Datei nicht modifiziert wurde. Ich lasse Sie das mit dem folgenden Befehl selbst überprüfen:

head -5 MIT.LICENSE

2. Text ersetzen … schon wieder

Toll:Wir haben den Jahresplatzhalter ersetzt. Aber es gibt einen zweiten zu ersetzen. Wenn Sie das vorherige Beispiel verstanden haben, könnten Sie sich wahrscheinlich einen zweiten sed-Ausdruck wie diesen vorstellen:

's/<COPYRIGHT HOLDER>/Sylvain Leroux/'

Aber wo soll man das hinstellen? Nun, Sie haben mehrere Möglichkeiten. Wenn Sie bereits mit dem Konzept der Umleitung vertraut sind, ist es am offensichtlichsten, die Ausgabe unseres ersten sed-Befehls an eine zweite Instanz von sed zu leiten:

[email protected]:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  |
    sed -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' |
    head -5
----8<----------------------------------------------------------------
Copyright 2018 Sylvain Leroux

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

Aber wir können es besser machen. Da das -e Option einen sed-Ausdruck einführt, können wir mehrere davon als Teil desselben sed-Aufrufs verwenden, und das Ergebnis ist dasselbe:

# Pay special attention to the \ at the end of the lines
# specifying the *same* command continues on the
# next line:
sh$ sed -e 's/<YEAR>/2018/'  \
                -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
                MIT.LICENSE |
        head -5

Schließlich können Sie auch mehrere Befehle im selben sed-Ausdruck angeben, indem Sie sie durch eine neue Zeile trennen. Dies ist besonders nützlich, wenn Sie anfangen, komplexere sed-Programme zu schreiben:

# Pay special attention to the single-quotes and
# backslash placement:
sh$ sed -e 's/<YEAR>/2018/
            s/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        MIT.LICENSE |
    head -5

3. Text einfügen

Jetzt haben wir die Platzhalter durch ihren tatsächlichen Wert ersetzt. Aber wir müssen noch etwas tun, bevor wir diese Lizenzdatei in die Projektdateien einfügen können. Da es sich später um Shell-Skripte handelt, muss jede Zeile der Lizenz mit einem Oktothorp (# ), damit die Shell sie versteht, sollte nicht versuchen, diese Zeilen zu interpretieren.

Dafür verwenden wir wieder den Substitutionsbefehl. Etwas, das ich zuvor nicht erwähnt habe, ist, dass das Suchmuster im Gegensatz zu den meisten Suchen-Ersetzen-Funktionen von GUI-Editoren nicht unbedingt die wörtliche Zeichenfolge ist, nach der gesucht werden soll. Tatsächlich ist dies ein regulärer Ausdruck (Regex). Das bedeutet, dass Sie neben einfachen Zeichen, die wörtlich übereinstimmen, auch Zeichen verwenden können, die eine besondere Bedeutung haben. Das Caretzeichen (^ ) stellt den Anfang der Zeile dar, das Dollarzeichen ($ ) das Ende der Zeile oder, als letztes Beispiel, der Punkt-Stern (.*). ) bedeutet eine beliebige Folge von 0, 1 oder mehreren Zeichen. Es gibt viele andere solcher Metazeichen, aber für den Moment ist dies mehr als genug.

Also zum Einfügen etwas Text am Anfang einer Zeile, eine Option ist Ersetzen den Beginn der Zeile durch diesen Text:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5
# -----8<----------------------------------------------------------------
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

4. Ausgewählte Zeilen löschen

Der Substitutionsbefehl in sed ist so vielseitig, dass Sie die meisten Texttransformationen damit ausdrücken können. Um beispielsweise die gestrichelten Linien oben und unten im Lizenztext zu entfernen, könnte ich Folgendes schreiben:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e 's/^.*----.*$//' \
        MIT.LICENSE | head -5

# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

Diese spätere Ersetzung hat den gesamten Text durch die leere Zeichenfolge ersetzt:

Symbol Beschreibung
^ Beginnend am Zeilenanfang
.* Gefolgt von einer beliebigen Folge von 0, 1 oder mehreren Zeichen
---- Gefolgt von 4 Bindestrichen
.* Gefolgt von einer beliebigen Folge von 0, 1 oder mehreren Zeichen
$ Gefolgt vom Zeilenende

Kurz gesagt, dies ersetzt die gesamte Zeile durch den leeren String if es enthält vier Bindestriche hintereinander. Aber die Leerzeile selbst bleibt in der Ausgabe und erscheint als Leerzeile.

Abhängig von Ihren genauen Bedürfnissen und Ihrem Geschmack möchten Sie vielleicht auch die folgende alternative Lösung in Betracht ziehen. Ich lasse Sie das im Detail untersuchen, um die Änderungen im Befehl zu lokalisieren und selbst festzustellen, was die Auswirkungen auf das Ergebnis waren:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^.*----.*$//' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5

Wenn Sie den zum Löschen der Zeile verwendeten regulären Ausdruck etwas zu komplex finden, können wir auch von einer anderen sed-Funktion profitieren. Fast alle Befehle können eine optionale Adresse vor dem Befehlsnamen annehmen. Falls vorhanden, beschränkt es den Umfang des Befehls auf die Zeilen matching diese Adresse:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/s/^.*$//' \
        MIT.LICENSE | head -5

Jetzt wird der letzte Ersetzungsbefehl nur auf Zeilen angewendet, die mit vier Bindestrichen hintereinander übereinstimmen (d. h. „enthalten“). Und für jede übereinstimmende Zeile wird alles ersetzt (.* ) zwischen dem Start (^ ) und Ende ($ ) der Zeile durch den leeren String (// )

5. Ausgewählte Zeilen entfernen

Im vorherigen Abschnitt haben wir den Ersetzungsbefehl optimiert, um einige Textzeilen zu löschen. Aber die Leerzeilen blieben bestehen. Manchmal ist dies wünschenswert. Manchmal ist es nicht. In letzterem Fall sollten Sie die Löschung untersuchen Befehl, um ganze Zeilen aus der Ausgabe zu entfernen:

# Below, the redirection '> LICENSE' is used to store
# the result of the sed command into the newly
# created LICENSE file:
[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/d' \
        MIT.LICENSE > LICENSE
[email protected]:~$ head -5 LICENSE
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including

Das d ist das Löschen Befehlsname. Genau wie die s war die Ersetzung Befehlsname. Hier haben wir vor dem Befehl eine Adresse angegeben, sodass nur übereinstimmende Zeilen entfernt werden (ohne Adresse wird das d hätte jede Zeile der Datei gelöscht)

6. In Großbuchstaben umwandeln

Bisher haben wir uns hauptsächlich auf den Anfang der Lizenzdatei konzentriert. Aber in der Tat gibt es einige Änderungen, die ich etwas weiter in den Dokumenten vornehmen möchte. Lassen Sie uns zuerst sehen, wovon ich spreche:

[email protected]:~$ sed -ne '/The above/,$p' LICENSE
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# The software is provided "as is", without warranty of any kind,
# express or implied, including but not limited to the warranties of
# merchantability, fitness for a particular purpose and noninfringement.
# In no event shall the authors or copyright holders be liable for any
# claim, damages or other liability, whether in an action of contract,
# tort or otherwise, arising from, out of or in connection with the
# software or the use or other dealings in the software.

Im obigen Befehl habe ich mit der Option -n das automatische Drucken des Musterbereichs deaktiviert. Das bedeutet, dass sed nichts mehr auf die Ausgabe druckt, es sei denn, ich fordere es ausdrücklich dazu auf. Genau das mache ich mit dem Befehl print (p). Beachten Sie, dass ich anstelle einer einzelnen Adresse vor dem p-Befehl einen Bereich verwendet habe um den Text zwischen der Zeile mit dem Text „The above“ und dem Ende des Dokuments ($) anzuzeigen.

Der Druckbefehl kann nützlich sein, wenn Sie einige Teile einer Datei extrahieren müssen. Für heute wollte ich jedoch nur die letzten beiden Absätze anzeigen, um zu erklären, was ich jetzt brauche:Da es bei Lizenzdateien eine Tradition ist, möchte ich mich damit absichern, dass die Software „wie besehen“ bereitgestellt wird. Daher möchte ich den letzten Absatz (beginnend mit „Die Software“) hervorheben, indem ich ihn komplett in Großbuchstaben umschreibe.

Im Ersetzungsteil eines Ersetzungsbefehls wird ein &durch den zum Suchmuster passenden Text ersetzt. Mit der GNU-Erweiterung \U können wir die Groß-/Kleinschreibung der Ersetzungszeichenfolge ändern:

[email protected]:~$ sed -i -e '/The software/,$s/.*/\U&/' LICENSE
[email protected]:~$ cat LICENSE

Im Klartext s/.*/\U&/ bedeutet „beliebigen Text ersetzen (.* ) durch den Großbuchstaben (\U ) Version von sich selbst (& ). Ich lasse Sie selbst überprüfen, der letzte Absatz sollte jetzt in Großbuchstaben geschrieben werden. Übrigens ist Ihnen vielleicht schon das -i aufgefallen Flag wurden die Änderungen direkt in die LICENSE-Datei übernommen.

Wir werden das im nächsten Abschnitt genauer sehen. In der Zwischenzeit lasse ich Sie diese Befehle nach Belieben üben und modifizieren. Sobald Sie eine Lizenzdatei haben, die Ihrem Geschmack entspricht, wird es Zeit zu sehen, wie Sie sie vor jeder Quelldatei des Projekts einfügen können.

7. Einfügen einer Textdatei

Wenn Sie hier einen komplizierten Befehl erwarten, werden Sie enttäuscht sein:Das Einfügen einer Datei in eine andere ist ziemlich einfach:

sed -i -e '1r LICENSE' script1.sh
cat script1.sh

Hier gibt es zwei Dinge zu sehen:

  1. die r LICENSE Ausdruck ist der Befehl zum lesen und fügen Sie eine externe Datei in die gerade verarbeitete Datei ein. Ihm wird hier die Zahl 1 vorangestellt Dies ist eine Adresse, die nur mit Zeile 1 der Eingabedatei übereinstimmt.
  2. das -i Option erlaubt das Ändern einer Datei an Ort und Stelle . Das bedeutet, dass sed hinter den Kulissen eine temporäre Datei erstellt, um seine Ausgabe dort zu speichern, und sobald die Verarbeitung abgeschlossen ist, wird es die Originaldatei durch die geänderte ersetzen.

Ein interessanter Nebeneffekt der Option „-i“ ist, dass Sie mehrere Dateinamen auf der Befehlszeile angeben können und sed unabhängig dieselben Transformationen auf jeden von ihnen anwendet :

sed -i -e '1r LICENSE' *.sh

8. Zurück in die Zukunft

Stellen wir uns als letztes Beispiel für den Befehl sed vor, dass einige Jahre vergangen sind und wir jetzt den 1. Januar 2024 haben. Der Urheberrechtshinweis aller Dateien muss aktualisiert werden. Je nachdem, wann die Projektdateien erstellt wurden, gibt es mehrere Anwendungsfälle. Daher sollten unsere Urheberrechtshinweise einem dieser beiden Formate folgen:

Aktuelles Urheberrecht Beschreibung
Urheberrecht 2023 Für letztes Jahr erstellte Dateien
Urheberrecht 2018-2023 Für Dateien, die vor dem letzten Jahr erstellt wurden

Wir können diese beiden Anwendungsfälle gleichzeitig mit einem erweiterten (-E) regulären Ausdruck erfassen. Die einzigen „erweiterten“ Dinge, die wir hier wirklich verwenden werden, sind die Klammern:

sed -i -Ee 's/Copyright (....)(-....)?/Copyright \1-2024/' *.sh

Ich empfehle Ihnen, den Copyright-Hinweis in den *.sh-Dateien manuell zu ändern und dann den obigen Befehl in verschiedenen Anwendungsfällen auszuführen, um zu sehen, wie er funktioniert.

Es könnte Ihrem Verständnis eventuell helfen, wenn ich im Suchmuster sage:Copyright::ist ein wörtlicher Text, der wörtlich übereinstimmt; (… .)::definiert eine einfangende Gruppe, die vier beliebige Zeichen enthält. Hoffentlich die vier Ziffern eines Jahres; (-… .)?::definiert eine einfangende Gruppe, die mit einem Bindestrich gefolgt von vier beliebigen Zeichen übereinstimmt. Das Fragezeichen am Ende zeigt an, dass die Gruppe optional ist. Es kann in der Eingabezeile vorhanden sein oder auch nicht.

In der Ersetzungszeichenfolge:Copyright::ist ein wörtlicher Text, der wörtlich kopiert wird; \1::ist der Inhalt der ersten einfangenden Gruppe -2024::ist ein wörtlicher Text, der wörtlich kopiert wird.

Wenn Sie sich die Zeit genommen haben, den Befehl selbst zu überprüfen, sollte dies bestätigen, wenn ich diese Regeln auf die in der vorherigen Tabelle beschriebenen Anwendungsfälle anwende, erhalte ich so etwas:

Übereinstimmender Text \1 \2 Ersatzstring
Urheberrecht 2023 2023 Urheberrecht 2023-2024
Urheberrecht 2018-2023 2018 -2023 Urheberrecht 2018-2024

Zum Abschluss unseres SED-Leitfadens

Wir haben hier nur an der Oberfläche gekratzt. Der sed Werkzeug ist viel mächtiger als das. Aber auch wenn wir nur vier Befehle gesehen haben (s , p , d , und i ) und ein paar grundlegende Konstrukte für reguläre Ausdrücke (^ , $ , . , ? und .* ), haben Sie bereits genug Wissen, um viele zu lösen alltägliche Probleme.

Da ich ein Tutorial gerne mit einer kleinen Herausforderung beende, schlage ich Ihnen Folgendes vor:Wenn Sie das Support-Material heruntergeladen haben, finden Sie im Verzeichnis des Projekts eine Datei namens hello.c . Dies ist die Quelldatei eines einfachen C-Programms:

[email protected]:~$ ls
hello.c  MIT.LICENSE  script1.sh  script2.sh
[email protected]:~$ gcc hello.c -o hello
[email protected]:~$ ./hello sylvain
Hello sylvain
[email protected]:~$ cat hello.c

Es gibt bereits einige Kommentare in der Quelldatei. Indem Sie sie als Beispiele für die Kommentarsyntax in der Programmiersprache C verwenden, könnten Sie die MIT-Lizenz in hello.c einfügen Quelldatei mit dem Befehl sed? Sie können einen oder mehrere sed-Befehle verwenden, Sie können die Ausgabe eines sed-Befehls in einen anderen leiten, Sie können temporäre Dateien verwenden, wenn Sie möchten, aber Sie sind nicht erlaubt, jeden anderen Befehl als sed zu verwenden. Die C-Quelldatei sollte natürlich nach dem Einfügen der Lizenz noch kompiliert werden!

Ich lasse Sie jetzt über dieses kleine Problem nachdenken und hoffe, dass Ihnen dieser Artikel und das dazugehörige Video gefallen haben. Wenn Sie mehr über sed erfahren möchten, lassen Sie es uns im Kommentarbereich wissen!


Linux
  1. Erste Schritte mit Zsh

  2. Erste Schritte mit dem Linux-tac-Befehl

  3. Erste Schritte mit dem Linux-cat-Befehl

  4. Erste Schritte mit ls

  5. Erste Schritte mit PostgreSQL unter Linux

Erste Schritte mit dem Nano-Texteditor [Leitfaden für Anfänger]

Erste Schritte mit Markdown [Leitfaden für Anfänger]

Erste Schritte mit cPanel/WHM

Erste Schritte mit AWK Command [Leitfaden für Anfänger]

Erste Schritte mit Tmux [Leitfaden für Anfänger]

Erste Schritte mit dem Tar-Befehl