it-swarm.com.de

der Befehl sed mit der Option -i schlägt auf dem Mac fehl, funktioniert aber unter Linux

Ich habe erfolgreich den folgenden sed-Befehl zum Suchen/Ersetzen von Text in Linux verwendet:

sed -i 's/old_link/new_link/g' *

Wenn ich es jedoch auf meinem Mac OS X versuche, bekomme ich:

"Befehl c erwartet\gefolgt von Text"

Ich dachte, mein Mac hat eine normale BASH-Shell. Wie geht's?

BEARBEITEN:

Laut @High Performance liegt dies daran, dass Mac sed eine andere (BSD-) Variante hat. Meine Frage wäre also, wie repliziere ich diesen Befehl in BSD sed?

BEARBEITEN:  

Hier ist ein aktuelles Beispiel, das dies verursacht:

sed -i 's/hello/gbye/g' *
231
Yarin

Wenn Sie die Option -i verwenden, müssen Sie eine Erweiterung für Ihre Sicherungen angeben.

Wenn Sie haben:

File1.txt
File2.cfg

Der Befehl (beachten Sie den Mangel an Platz zwischen -i und '' und -e, damit er auf neuen Versionen von Mac und auf GNU funktioniert):

sed -i'.original' -e 's/old_link/new_link/g' *

erstellen Sie 2 Sicherungsdateien wie:

File1.txt.original
File2.cfg.original

Es gibt keinen tragbaren Weg, um die Erstellung von Sicherungsdateien zu vermeiden, da es unmöglich ist, eine Kombination aus sed-Befehlen zu finden, die in allen Fällen funktioniert:

  • sed -i -e ... - funktioniert nicht unter OS X, da -e-Sicherungen erstellt werden
  • sed -i'' -e ... - funktioniert nicht unter OS X 10.6, funktioniert jedoch unter 10.9+
  • sed -i '' -e ... - funktioniert nicht mit GNU

Hinweis Da es keinen sed-Befehl gibt, der auf allen Plattformen funktioniert, können Sie versuchen, einen anderen Befehl zu verwenden, um dasselbe Ergebnis zu erzielen

z.B. Perl -i -pe's/old_link/new_link/g' *

322
Sinetris

Ich glaube unter OS X, wenn Sie -i verwenden, ist eine Erweiterung für die Sicherungsdateien erforderlich . Versuchen:

sed -i .bak 's/hello/gbye/g' *

Mit GNU sed ist die Erweiterung optional .

44

Dies funktioniert sowohl mit GNU als auch mit BSD-Versionen von sed:

sed -i'' -e 's/old_link/new_link/g' *

oder mit backup:

sed -i'.bak' -e 's/old_link/new_link/g' *

Fehlendes Leerzeichen nach -i-Option beachten! (Notwendig für GNU sed)

42
chipiik

Hatte das gleiche Problem in Mac und löste es mit brew:

brew install gnu-sed

und verwenden als

gsed SED_COMMAND

sie können sed als Alias ​​auch auf gsed setzen (wenn Sie möchten):

alias sed=gsed
19
Sruthi Poddutur

Sie können auch die GNU - Version von sed (gsed) in Ihrem Mac installieren und mit der Linux-Standardsyntax verwenden.

Installieren Sie dazu gsed mit Ports (wenn Sie nicht über diese verfügen, erhalten Sie sie unter http://www.macports.org/ ), indem Sie Sudo port install gsed ausführen. Dann können Sie sed -i 's/old_link/new_link/g' * ausführen.

14
Ohad Kravchick

Die Antwort von Sinetris ist richtig, aber ich verwende dies mit dem Befehl find, um genauer zu sagen, welche Dateien ich ändern möchte. Im Allgemeinen sollte dies funktionieren (getestet mit osx /bin/bash):

find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;

Im Allgemeinen ist die Verwendung von sed ohne find in komplexen Projekten weniger effizient.

8
Lucas

Ihr Mac hat zwar eine BASH-Shell, aber es ist eher eine Frage, mit welcher Implementierung von sed Sie sich befassen. Auf einem Mac kommt Sed aus BSD und unterscheidet sich geringfügig von dem, den Sie in einer typischen Linux-Box finden. Ich schlage vor, Sie man sed.

So können Sie Umgebungsvariablen auf die Vorlagendatei anwenden (kein Backup erforderlich).

1. Erstellen Sie mit {{FOO}} eine Vorlage zum späteren Ersetzen.

echo "Hello {{FOO}}" > foo.conf.tmpl

2. Ersetzen Sie {{FOO}} durch die Variable FOO und geben Sie sie in die neue Datei foo.conf ein

FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf

Beide arbeiten - macOS 10.12.4 und Ubuntu 14.04.5

1
katopz
sed -ie 's/old_link/new_link/g' *

Funktioniert sowohl unter BSD als auch unter Linux

0
ashokrajar

Wie die anderen Antworten zeigen, gibt es keine Möglichkeit, Sed port portabel unter OS X und Linux zu verwenden, ohne Sicherungsdateien zu erstellen. Also habe ich stattdessen diesen Ruby One-Liner dazu benutzt:

Ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml

In meinem Fall musste ich es von einer rake-Task aus aufrufen (d. H. Innerhalb eines Ruby-Skripts). Daher habe ich diese zusätzliche Zitierstufe verwendet:

sh %q{Ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}
0
dankohn

Ich habe eine Funktion erstellt, um sed Unterschied zwischen MacOS (getestet unter MacOS 10.12) und anderen Betriebssystemen zu behandeln:

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "$1" "$2"
    else
        # for Linux and Windows
        sed -i'' -e "$1" "$2"
    fi
}

Verwendungszweck:

$(replace_in_file 's,MASTER_Host.*,MASTER_Host='"$MASTER_IP"',' "./mysql/.env")

Woher:

, ist ein Delimeter

's,MASTER_Host.*,MASTER_Host='"$MASTER_IP"',' ist Muster

"./mysql/.env" ist der Pfad zur Datei

0
v.babak