In-Place-Änderungen mit sed unter OS X.

142

Ich möchte eine Datei mit sed unter OS X bearbeiten. Ich verwende den folgenden Befehl:

sed 's/oldword/newword/' file.txt

Die Ausgabe wird an das Terminal gesendet. file.txt wird nicht geändert. Die Änderungen werden mit diesem Befehl in file2.txt gespeichert :

sed 's/oldword/newword/' file1.txt > file2.txt

Ich möchte jedoch keine weitere Datei. Ich möchte nur file1.txt bearbeiten . Wie kann ich das machen?

Ich habe die -i-Flagge ausprobiert. Dies führt zu folgendem Fehler:

sed: 1: "file1.txt": invalid command code f
Sonntag Montag
quelle
2
Was ist der genaue Befehl, den Sie verwenden, wenn Sie die -iFlagge ausprobieren ?
Eldarerathis

Antworten:

281

Sie können das -iFlag korrekt verwenden, indem Sie ihm ein Suffix zum Hinzufügen zur gesicherten Datei hinzufügen. Erweitern Sie Ihr Beispiel:

sed -i.bu 's/oldword/newword/' file1.txt

Sie erhalten zwei Dateien: eine mit dem Namen file1.txt, der die Ersetzung enthält, und eine mit dem Namen file1.txt.bu, der den ursprünglichen Inhalt enthält.

Leicht gefährlich

Wenn Sie die Originaldatei destruktiv überschreiben möchten, verwenden Sie Folgendes:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

Aufgrund der Art und Weise, wie die Zeile analysiert wird, ist zwischen dem Optionsflag und seinem Argument ein Leerzeichen erforderlich, da das Argument die Länge Null hat.

Abgesehen davon, dass Sie möglicherweise Ihr Original wegwerfen, sind mir keine weiteren Gefahren bewusst, wenn Sie auf diese Weise ausgetrickst werden. Es sollte jedoch beachtet werden, dass sedThe Unix Way ™ (IMHO) , wenn dieser Aufruf von Teil eines Skripts ist, sedzerstörungsfrei zu verwenden ist, zu testen, ob es sauber beendet wurde, und erst dann die fremde Datei zu entfernen.

schnitzen
quelle
Sie haben Recht, ich habe die Erweiterung nach der Flagge -i weggelassen. Ist es -i''aus einem anderen Grund gefährlich, als die Originaldatei möglicherweise durcheinander zu bringen (und keine Sicherung zu haben)?
Sonntag Montag,
Laut der sedManpage könnten Sie eine Datei mitten im Schritt beschädigen und ein schlechtes Ausgabeergebnis erzielen, wenn Ihnen der Speicherplatz auf dem Gerät ausgeht. Wenn Sie unter lokaler Quellcodeverwaltung sed -i ""ohne Backups arbeiten, sollte dies die meiste Zeit in Ordnung sein (oder kurz git init && git add -A . && git commit -m 'backup'bevor Sie sed im -iModus ausführen ).
cfeduke
2
Ich fand das leicht gefährliche Stück besonders nützlich. +1
Andre
5
BSD sed erfordert, dass nach dem Flag -i kein Leerzeichen steht. Also, -i''ist gültig, aber -i ''nicht.
Todd A. Jacobs
3
Argh! BSD sed ignoriert das Zeichen '\ n' und druckt stattdessen 'n'! Ich werde nur BSD sed durch GNU sed auf meinem Mac ersetzen!
nterry
20

Ich habe ein ähnliches Problem mit MacOS

sed -i '' 's/oldword/newword/' file1.txt

funktioniert nicht, aber

sed -i"any_symbol" 's/oldword/newword/' file1.txt

funktioniert gut.

ksnt
quelle
Dies ist jetzt umgekehrt. sed -i '' <file>funktioniert, funktioniert aber sed -i'' <file>nicht mehr
Zohaib Amanzai
7
sed -i -- "s/https/http/g" file.txt
jazzed
quelle
4

Sie können -i''( --in-place) für sedwie bereits vorgeschlagen verwenden. Siehe: Das -iIn-Place-Argument . Beachten Sie jedoch, dass es sich bei der -iOption um nicht standardmäßige FreeBSD-Erweiterungen handelt, die unter anderen Betriebssystemen möglicherweise nicht verfügbar sind. Zweitens sedist ein S tream ED itor, kein Datei-Editor .


Eine alternative Möglichkeit besteht darin, die integrierte Substitution im Vim Ex-Modus zu verwenden, z.

$ ex +%s/foo/bar/g -scwq file.txt

und für mehrere Dateien:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

Um alle Dateien rekursiv zu bearbeiten, können Sie verwenden, **/*.*wenn die Shell dies unterstützt (aktivieren durch shopt -s globstar).


Eine andere Möglichkeit ist die Verwendung gawkund die neue "Inplace" -Erweiterung wie:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
Kenorb
quelle
4

Dadurch werden Sicherungsdateien erstellt. ZB erstellt sed -i -e 's/hello/hello world/' testfilefür mich eine Sicherungsdatei, testfile-e, im selben Verzeichnis.

JustADude
quelle
Gleiches gilt hier für Mac OS Catalina. Wenn Sie -i und -e getrennt übergeben (NICHT -ie zusammen!), Wird eine Sicherungsdatei mit dem Anhang '-e' erstellt.
Daniel Kesner
1

Sie können verwenden:

sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>

Beispiel:

sed -i -e 's/Hello/Bye/' file.txt

Dies funktioniert einwandfrei in Mac .

Vincent Lal
quelle
2
Dadurch wird in Mac OS Catalina eine Sicherungsdatei für mich erstellt, an die '-e' angehängt ist.
Daniel Kesner
Dies ist falsch für macOS. Bitte schauen Sie sich dort die Seite "man sed" an. -ierfordert ein Argument für macOS. Da Sie keine angeben, wird diese verwendet -e, was dazu führt, dass eine zweite Datei -eangehängt wird. -eexistiert nicht in macOS, es ist -E. Der richtige Befehl für macOS lautet alsosed -i '' -E 's/Hello/Bye/' file.txt
Marc J. Schmidt