it-swarm.com.de

Wie führe ich den Befehl sed mit Eingabe und Ausgabe als dieselbe Datei aus?

Ich versuche, den sed-Befehl in einem Shell-Skript zu verwenden, in dem ich Zeilen mit dem Namen STARTremoveThisComment und Zeilen mit dem Namen removeThisCommentEND entfernen möchte.

Ich kann es tun, wenn ich es mit in eine neue Datei kopiere

sed 's/STARTremoveThisComment//' > test

Aber wie mache ich das, indem ich die gleiche Datei als Ein- und Ausgabe verwende?

49

sed -i (oder die erweiterte Version, --in-place) automatisiert den Vorgang, der normalerweise mit weniger fortgeschrittenen Implementierungen durchgeführt wird, dh das Senden der Ausgabe an eine temporäre Datei und das anschließende Umbenennen in das Original.

Das -i ist für die direkte Bearbeitung vorgesehen. Sie können auch ein Sicherungssuffix für die Aufbewahrung einer Kopie des Originals angeben:

sed -i.bak fileToChange
sed --in-place=.bak fileToChange

Beide behalten die Originaldatei in fileToChange.bak.

Beachten Sie, dass die direkte Bearbeitung möglicherweise nicht in allen sed Implementierungen verfügbar ist, aber is in GNU sed das sollte auf allen Linux-Varianten verfügbar sein, je nach Ihren Tags.

Wenn Sie eine primitivere Implementierung verwenden, können Sie Folgendes verwenden:

sed 'whatever' oldfile >newfile ; mv newfile oldfile

obwohl mehr Fehlerprüfung wäre schön.

83
paxdiablo

Sie können das Flag - i für die direkte Bearbeitung und - e für die Angabe des normalen Skriptausdrucks verwenden:

sed -i -e 's/pattern_to_search/text_to_replace/' file.txt

Um Zeilen zu löschen, die einem bestimmten Muster entsprechen, können Sie die einfachere Syntax verwenden. Beachten Sie das d Flag:

sed -i '/pattern_to_search/d' file.txt
8
Tiago

Sie sollten sed wirklich nicht dafür verwenden. Diese Frage scheint lächerlich oft zu kommen, und es scheint sehr seltsam, dass es so ist, dass die Leute wissen wollen, wie man es in sed, in Python und in Ruby usw. Macht, da die allgemeine Lösung so trivial ist Wenn Sie möchten, dass ein Filter einen Eingang bearbeitet und überschreibt, verwenden Sie das folgende einfache Skript:

#!/bin/sh -e
in=${1?No input file specified}
mv $in ${bak=.$in.bak}
shift
"[email protected]" < $bak > $in

Fügen Sie das in Ihren Pfad in einen ausführbaren Dateinamen inline ein, und das Problem ist dann im Allgemeinen gelöst. Beispielsweise:

inline input-file sed -e s/foo/bar/g

Wenn Sie nun Logik hinzufügen möchten, um mehrere Backups zu speichern, oder wenn Sie einige Optionen zum Ändern des Backup-Benennungsschemas oder was auch immer haben, können Sie dies an einem Ort beheben. Was ist die Befehlszeilenoption, um 1-up-Zähler für die Sicherungsdatei zu erhalten, wenn eine Datei mit Perl direkt verarbeitet wird? Was ist mit Ruby? Unterscheidet sich die Option für gnu-sed? Wie geht awk damit um? Der ganze Punkt von Unix ist, dass Werkzeuge nur eine Sache tun. Die Handhabung der Logik für Sicherungsdateien ist eine zweite Sache und muss herausgerechnet werden. Wenn Sie ein Tool implementieren, fügen Sie keine Logik zum Erstellen von Sicherungsdateien hinzu. Bitten Sie Ihre Benutzer, dafür ein zweites Tool zu verwenden. Integration ist schlecht. Modularität ist gut. Das ist der Unix-Weg.

Beachten Sie, dass dieses Skript mehrere Probleme hat. Die Berechtigungen/der Modus der Eingabedatei können beispielsweise geändert werden. Ich bin sicher, es gibt unzählige andere Probleme. Indem Sie jedoch die Sicherungslogik in ein Wrapper-Skript einfügen, lokalisieren Sie all diese Probleme und müssen sich keine Sorgen machen, dass sed die Dateien und den Änderungsmodus überschreibt, während python die Datei in sich behält place und ändert den inode nicht

5
William Pursell

Ich schlage vor, sponge zu verwenden

schwamm liest die Standardeingabe und schreibt sie in die angegebene Datei. Im Gegensatz zu einer Shell-Umleitung nimmt der Schwamm alle Eingaben auf, bevor die Ausgabedatei geschrieben wird. Auf diese Weise können Pipelines erstellt werden, die aus derselben Datei lesen und in dieselbe Datei schreiben.

cat test | sed 's/STARTremoveThisComment//' | sponge test
0
Benjamin Peter

Soweit ich weiß, ist es nicht möglich, dieselbe Datei für die Ein- und Ausgabe zu verwenden. Obwohl eine Lösung darin besteht, ein Shell-Skript zu erstellen, das es in einer anderen Datei speichert, löschen Sie die alte Eingabe und benennen Sie die Ausgabe in den Namen der Eingabedatei um.

sed -e s/try/this/g input.file > output.file;mv output.file input.file
0
JudeJitsu