Ich versuche herauszufinden, ob es möglich ist, eine Datei in einem einzigen sed-Befehl zu bearbeiten, ohne den bearbeiteten Inhalt manuell in eine neue Datei zu streamen und die neue Datei dann in den ursprünglichen Dateinamen umzubenennen. Ich habe die -i
Option ausprobiert, aber mein Solaris-System hat angegeben, dass dies -i
eine illegale Option ist. Gibt es einen anderen Weg?
300
-i
ist eine Option in gnu sed, aber nicht in Standard sed. Der Inhalt wird jedoch in eine neue Datei gestreamt und anschließend umbenannt, sodass er nicht Ihren Wünschen entspricht.Antworten:
Die
-i
Option überträgt den bearbeiteten Inhalt in eine neue Datei und benennt ihn dann trotzdem hinter den Kulissen um.Beispiel:
und
unter macOS .
quelle
sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
Auf einem System, auf dem
sed
Dateien nicht bearbeitet werden können, ist meiner Meinung nach die bessere Lösungperl
:Obwohl dadurch eine temporäre Datei erstellt wird, wird das Original ersetzt, da ein leeres Suffix / eine leere Erweiterung angegeben wurde.
quelle
sudo
. In meinen Augen geht es darum, wie man das manuelle Erstellen und Umbenennen einer temporären Datei vermeidet, ohne die neueste GNU oder BSD installieren zu müssensed
. Verwenden Sie einfach Perl.sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt
. Nur weil die direkte Bearbeitung die Umbenennung mithilfe einer temporären Datei vornimmt, bedeutet dies nicht, dass er / sie eine manuelle Umbenennung durchführen muss , wenn die Option nicht verfügbar ist. Es gibt andere Tools, die tun können, was er / sie will, und Perl ist die offensichtliche Wahl. Wie ist das keine Antwort auf die ursprüngliche Frage?sed
. Die Frage war eigentlich sehr gut, aber ihr Wert wurde von Leuten gemindert, die entweder keine Manpages lesen können oder sich nicht die Mühe machen, hier auf SO tatsächlich Fragen zu lesen.Beachten Sie, dass unter OS X möglicherweise seltsame Fehler wie "ungültiger Befehlscode" oder andere seltsame Fehler auftreten, wenn Sie diesen Befehl ausführen. Um dieses Problem zu beheben, versuchen Sie es
Dies liegt daran, dass in der OSX-Version von
sed
die-i
Option einextension
Argument erwartet , sodass Ihr Befehl tatsächlich alsextension
Argument analysiert und der Dateipfad als Befehlscode interpretiert wird. Quelle: https://stackoverflow.com/a/19457213quelle
brew install gnu-sed
zusammen mit aPATH
die GNU-Version von sed verwenden. Vielen Dank für die Erwähnung; ein definitiver Kopfkratzer.Das Folgende funktioniert gut auf meinem Mac
Wir ersetzen foo durch bar in der Beispieldatei. Die Sicherung der Originaldatei wird in sample.bak gespeichert
Verwenden Sie den folgenden Befehl, um Inline ohne Backup zu bearbeiten
quelle
Eine Sache zu beachten,
sed
kann Dateien nicht alleine schreiben, da der einzige Zweck von sed darin besteht, als Editor für den "Stream" zu fungieren (dh Pipelines von stdin, stdout, stderr und anderen>&n
Puffern, Sockets und dergleichen). In diesem Sinne können Sie einen anderen Befehl verwendentee
, um die Ausgabe zurück in die Datei zu schreiben. Eine andere Möglichkeit besteht darin, einen Patch zu erstellen, aus dem der Inhalt weitergeleitet wirddiff
.Tee-Methode
Patch-Methode
AKTUALISIEREN:
Beachten Sie außerdem, dass durch Patch die Datei von Zeile 1 der Diff-Ausgabe geändert wird:
Patch muss nicht wissen, auf welche Datei zugegriffen werden soll, da sich diese in der ersten Zeile der Ausgabe von diff befindet:
quelle
/dev/stdin 2014-03-15
, antwortete 7. Januar - bist du ein Zeitreisender?/dev/stdin
nicht vorhanden, daher müssen Sie/dev/stdin
einen einzelnen Bindestrich ohne Anführungszeichen durch '-' ersetzen , damit die folgenden Befehle funktionieren:$ sed 's/oo/u/' fubar | diff -p fubar -
und$ sed 's/oo/u/' fubar | diff -p fubar - | patch
patch
ich nicht auch abschneiden werde. Ich denke, das Speichern der Ausgabe in einer anderen Datei und das anschließendecat
Einfügen in das Original wäre sicherer.Es ist nicht möglich zu tun, was Sie wollen
sed
. Sogar Versionensed
davon unterstützen die-i
Option zum Bearbeiten einer vorhandenen Datei und tun genau das, was Sie ausdrücklich angegeben haben, dass Sie nicht möchten: Sie schreiben in eine temporäre Datei und benennen die Datei dann um. Aber vielleicht können Sie einfach verwendened
. Um beispielsweise alle Vorkommen vonfoo
tobar
in der Datei zu ändernfile.txt
, haben Sie folgende Möglichkeiten:Die Syntax ist ähnlich
sed
, aber sicherlich nicht genau gleich.Aber vielleicht sollten Sie überlegen, warum Sie keine umbenannte temporäre Datei verwenden möchten. Selbst wenn Sie keine
-i
Unterstützung habensed
, können Sie einfach ein Skript schreiben, um die Arbeit für Sie zu erledigen. Stattdessensed -i 's/foo/bar/g' file
könnten Sie tuninline file sed 's/foo/bar/g'
. Ein solches Skript ist trivial zu schreiben. Zum Beispiel:sollte für die meisten Anwendungen ausreichend sein.
quelle
inline
und es wie oben beschrieben aufrufen:inline inputfile sed 's/foo/bar/g'
ed
nur eine Antwort, die wirklich an Ort und Stelle ist. Zum ersten Mal brauche ich jemalsed
. Danke dir. Eine kleine Optimierung ist zu verwendenecho -e ",s/foo/bar/g\012 w"
oderecho $',s/foo/bar/g\012 w'
wo Shell es erlaubt, zusätzlichetr
Anrufe zu vermeiden .ed
macht die Änderungen nicht wirklich an Ort und Stelle. Aus derstrace
Ausgabeed
erstellt GNU eine temporäre Datei, schreibt die Änderungen in die temporäre Datei und schreibt dann die gesamte Originaldatei neu, wobei feste Links erhalten bleiben. Bei dertruss
Ausgabe verwendet Solaris 11ed
auch eine temporäre Datei, benennt die temporäre Datei jedoch beim Speichern mit demw
Befehl in den ursprünglichen Dateinamen um, wodurch alle festen Links zerstört werden.ed
, das mit aktuellen Macos geliefert wird (Mojave, was auch immer dieser Marketing-Jargon bedeutet), behält weiterhin Hardlinks bei. YMMVSie könnten vi verwenden
quelle
sed unterstützt die direkte Bearbeitung. Von
man sed
:Beispiel :
Angenommen, Sie haben eine Datei
hello.txt
mit dem Text:Wenn Sie eine Sicherungskopie der alten Datei erstellen möchten, verwenden Sie:
Sie erhalten zwei Dateien:
hello.txt
mit dem Inhalt:und
hello.txt.bak
mit dem alten Inhalt.Wenn Sie keine Kopie behalten möchten, übergeben Sie einfach nicht den Erweiterungsparameter.
quelle
Sie haben nicht angegeben, welche Shell Sie verwenden, aber mit zsh können Sie das
=( )
Konstrukt verwenden, um dies zu erreichen. Etwas in der Art von:=( )
ähnelt,>( )
erstellt jedoch eine temporäre Datei, die beimcp
Beenden automatisch gelöscht wird .quelle
Sollte alle Hardlinks beibehalten, da die Ausgabe zurückgeleitet wird, um den Inhalt der Originaldatei zu überschreiben, und die Notwendigkeit einer speziellen Version von sed vermieden wird.
quelle
Wenn Sie die gleiche Anzahl von Zeichen ersetzen und nach dem sorgfältigen Lesen der "In-Place" -Bearbeitung von Dateien ...
Sie können auch den Umleitungsoperator verwenden
<>
, um die Datei zum Lesen und Schreiben zu öffnen:Sehen Sie es live:
Aus dem Bash-Referenzhandbuch → 3.6.10 Öffnen von Dateideskriptoren zum Lesen und Schreiben :
quelle
Wie Moneypenny in Skyfall sagte: "Manchmal sind die alten Wege am besten." Kincade sagte später etwas Ähnliches.
Viel Spaß beim Bearbeiten. '\ Nw \ n' hinzugefügt, um die Datei zu schreiben. Entschuldigung für die verspätete Beantwortung der Anfrage.
quelle
|
. @ MattMontag\n
. [range] s / <old> / <new> / <flag> ist die Form des Ersatzbefehls - ein Paradigma, das noch in vielen anderen Texteditoren zu sehen ist (okay, vim, ein direkter Nachkomme von ed). Wie auch immer, dieg
Flagge steht für "global" und bedeutet "jede Instanz in jeder Zeile, die Sie betrachten". Der Bereich umfasst die3,5
Zeilen 3-5.,5
schaut auf StartOfFile-5,3,
schaut auf die Zeilen 3-EndOfFile und,
schaut auf StartOfFile-EndOfFile. Ein globaler Ersetzungsbefehl in jeder Zeile, der "false" durch "true" ersetzt. Dann wird der Schreibbefehlw
eingegeben.Sehr gute Beispiele. Ich hatte die Herausforderung, viele Dateien an Ort und Stelle zu bearbeiten, und die Option -i scheint die einzig vernünftige Lösung zu sein, die sie im Befehl find verwendet. Hier das Skript zum Hinzufügen von "version:" vor der ersten Zeile jeder Datei:
quelle