Gibt es einen Aufruf zur sed
direkten Bearbeitung ohne Backups, der sowohl unter Linux als auch unter Mac funktioniert? Während das sed
mit OS X gelieferte BSD anscheinend benötigt wird sed -i '' …
, sed
interpretieren die GNU Linux-Distributionen die Anführungszeichen normalerweise als leeren Eingabedateinamen (anstelle der Sicherungserweiterung) und benötigen sed -i …
stattdessen.
Gibt es eine Befehlszeilensyntax, die mit beiden Varianten funktioniert, sodass ich auf beiden Systemen dasselbe Skript verwenden kann?
Antworten:
Wenn Sie wirklich nur
sed -i
die "einfache" Methode verwenden möchten, funktioniert Folgendes sowohl auf GNU als auch auf BSD / Macsed
:Beachten Sie den Platzmangel und den Punkt.
Beweis:
Natürlich können Sie dann einfach die
.bak
Dateien löschen .quelle
sed
)sed
kein Positionsargument akzeptiert wird - es muss mit einem anderen Flag versehen werden . Somit wird der Befehl:command
-i
-e
sed -i.bak -e 's/foo/bar/' filename
sed -i.bak 's/foo/bar/' file && rm file.bak
Dies funktioniert mit GNU sed, jedoch nicht unter OS X:
Dies funktioniert unter OS X, jedoch nicht mit GNU sed:
Unter OS X Sie
sed -i -e
da die Erweiterung der Sicherungsdatei auf gesetzt wäre-e
sed -i'' -e
aus den gleichen Gründen nicht verwendet werden - es benötigt ein Leerzeichen zwischen-i
und''
.quelle
-i
und-i''
zum Zeitpunkt der Shell-Analyse identisch sind.sed
kann sich bei diesen beiden ersten Aufrufen nicht anders verhalten, da es genau die gleichen Argumente erhält.Unter OSX installiere ich die GNU sed-Version immer über Homebrew, um Probleme mit Skripten zu vermeiden, da die meisten Skripte für GNU sed-Versionen geschrieben wurden.
Dann wird Ihr BSD sed durch GNU sed ersetzt.
Alternativ können Sie ohne Standardnamen installieren, aber dann:
PATH
Anweisungen nach der Installationgnu-sed
gsed
odersed
abhängig von Ihrem System zu wählenquelle
--with-default-names
wurde aus dem Homebrew-Core entfernt , mehr Infos in dieser Antwort. bei der Installationgnu-sed
nun, geben Sie den Installationsanweisungen , die Sie hinzufügen müssen ,gnubin
um IhrePATH
:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Wie Noufal Ibrahim fragt, warum kannst du Perl nicht benutzen? Jeder Mac verfügt über Perl, und es gibt nur sehr wenige Linux- oder BSD-Distributionen, die keine Perl-Version im Basissystem enthalten. Eine der wenigen Umgebungen, in denen Perl möglicherweise tatsächlich fehlt, ist BusyBox (die wie GNU / Linux funktioniert
-i
, außer dass keine Backup-Erweiterung angegeben werden kann).Wie ismail empfiehlt,
und dies scheint in fast jedem Fall eine bessere Lösung zu sein als Skripte, Aliase oder andere Problemumgehungen, um die grundlegende Inkompatibilität
sed -i
zwischen GNU / Linux und BSD / Mac zu beheben.quelle
perl
ist seit dem 1. Mai 2009 Teil der Linux Standard Base-Spezifikation. refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/…Es gibt keine Möglichkeit, es zum Laufen zu bringen.
Eine Möglichkeit besteht darin, eine temporäre Datei wie die folgende zu verwenden:
Dies funktioniert bei beiden
quelle
Antwort: Nein.
Die ursprünglich akzeptierte Antwort macht tatsächlich nicht das, was angefordert wird (wie in den Kommentaren angegeben). (Ich habe diese Antwort gefunden, als ich nach dem Grund gesucht habe, warum a
file-e
"zufällig" in meinen Verzeichnissen angezeigt wurde.)Es gibt anscheinend keine Möglichkeit,
sed -i
sowohl unter MacOS als auch unter Linuces konsequent zu arbeiten.Meine Empfehlung lautet, nicht direkt zu aktualisieren
sed
(was komplexe Fehlermodi aufweist), sondern neue Dateien zu generieren und diese anschließend umzubenennen. Mit anderen Worten: vermeiden-i
.quelle
Die
-i
Option ist nicht Teil von POSIX Sed . Eine portablere Methode wäre die Verwendung von Vim im Ex-Modus:%
Wählen Sie alle Zeilen auss
ersetzenx
speichern und schließenquelle
Hier ist eine weitere Version, die unter Linux und MacOS funktioniert,
eval
ohne Sicherungsdateien zu verwenden und ohne sie löschen zu müssen. Es verwendet Bash-Arrays zum Speichern dersed
Parameter, was sauberer ist als die Verwendung voneval
:Dadurch wird weder eine Sicherungsdatei noch eine Datei mit angehängten Anführungszeichen erstellt.
quelle
sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '')
sed "${sedi[@]}" -e 's/foo/bar/' target.file
Steve Powells Antwort ist ganz richtig. Auf der MAN-Seite für sed unter OSX und Linux (Ubuntu 12.04) wird die Inkompatibilität innerhalb der "in-place" sed-Nutzung zwischen den beiden Betriebssystemen hervorgehoben.
JFYI, zwischen dem -i und Anführungszeichen (die eine leere Dateierweiterung bezeichnen) sollte unter Verwendung der Linux-Version von sed kein Leerzeichen stehen
sed Linux Man Page
und
sed OSX Manpage
Ich habe dies in einem Skript umgangen, indem ich einen Alias-Befehl und die OS-Namensausgabe von ' uname ' innerhalb einer Bash 'if' verwendet habe. Der Versuch, betriebssystemabhängige Befehlszeichenfolgen in Variablen zu speichern, war bei der Interpretation der Anführungszeichen ein Hit und Miss. Die Verwendung von ' shopt -s expand_aliases ' ist erforderlich, um die in Ihrem Skript definierten Aliase zu erweitern / verwenden. Die Verwendung von shopt wird hier behandelt .
quelle
Wenn Sie
sed
in einembash
Skript direkt vor Ort arbeiten müssen und NICHT möchten, dass das In-Place-Ergebnis zu .bkp-Dateien führt und Sie eine Möglichkeit haben, das Betriebssystem zu erkennen (z. B. mit ostype.sh ), - dann das Der folgende Hack mit derbash
eingebauten Shelleval
sollte funktionieren:quelle
Sie können Schwamm verwenden. Sponge ist ein altes Unix-Programm, das im Paket moreutils enthalten ist (sowohl in Ubuntu als auch wahrscheinlich in Debian und in Homebrew auf Mac).
Es puffert den gesamten Inhalt der Pipe, wartet, bis die Pipe geschlossen ist (was wahrscheinlich bedeutet, dass die Eingabedatei bereits geschlossen ist) und überschreibt dann:
Von der Manpage :
quelle
Folgendes funktioniert für mich unter Linux und OS X:
sed -i' ' <expr> <file>
zB für eine Datei
f
mitaaabbaaba
sed -i' ' 's/b/c/g' f
ergibt
aaaccaaca
sowohl auf Linux als auch auf Mac. Hinweis : Es gibt eine Zeichenfolge in Anführungszeichen ist ein Leerzeichen enthält , mit keinem Abstand zwischen dem-i
und dem String. Einfache oder doppelte Anführungszeichen funktionieren beide.Unter Linux verwende ich
bash
Version 4.3.11 unter Ubuntu 14.04.4 und unter Mac Version 3.2.57 unter OS X 10.11.4 El Capitan (Darwin 15.4.0).quelle
Ich bin auf dieses Problem gestoßen. Die einzige schnelle Lösung bestand darin, das sed in mac durch die gnu-Version zu ersetzen:
quelle