451 Stimmen

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

Ich habe Folgendes erfolgreich eingesetzt sed Befehl zum Suchen/Ersetzen von Text unter Linux:

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

Wenn ich es jedoch auf meinem Mac OS X versuche, erhalte ich eine Fehlermeldung:

"Befehl c erwartet \ gefolgt von Text"

Ich dachte, auf meinem Mac läuft eine normale BASH-Shell. Was ist los?

EDIT:

Nach Angaben von @High Performance ist dies auf den Mac zurückzuführen sed da es sich um eine andere (BSD) Variante handelt, wäre meine Frage, wie ich diesen Befehl in BSD replizieren kann sed ?

EDIT:

Hier ist ein konkretes Beispiel, das dies verursacht:

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

11voto

Lucas Punkte 2509

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

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

Im Allgemeinen wird bei der Verwendung von sed ohne find bei komplexen Projekten weniger effizient ist.

11voto

Anstelle des Aufrufs von sed mit sed Ich schon ./bin/sed

Und dies ist das Wrapper-Skript in meinem ~/project/bin/sed

#!/bin/bash

if [[ "$OSTYPE" == "darwin"* ]]; then
  exec "gsed" "$@"
else
  exec "sed" "$@"
fi

Vergessen Sie nicht chmod 755 das Wrapper-Skript.

8voto

v.babak Punkte 668

Ich habe eine Funktion erstellt, die Folgendes behandelt sed Unterschied zwischen MacOS (getestet mit MacOS 10.12) und anderen Betriebssystemen:

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
}

Verwendung:

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

Wo:

, ist ein Begrenzer

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

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

2voto

Igor Dolzhikov Punkte 179

Hier ist eine Option in Bash-Skripten:

#!/bin/bash

GO_OS=${GO_OS:-"linux"}

function detect_os {
    # Detect the OS name
    case "$(uname -s)" in
      Darwin)
        host_os=darwin
        ;;
      Linux)
        host_os=linux
        ;;
      *)
        echo "Unsupported host OS. Must be Linux or Mac OS X." >&2
        exit 1
        ;;
    esac

   GO_OS="${host_os}"
}

detect_os

if [ "${GO_OS}" == "darwin" ]; then
    sed -i '' -e ...
else
    sed -i -e ...
fi

1voto

Dan Kohn Punkte 32574

Wie die anderen Antworten zeigen, gibt es keine Möglichkeit, sed portabel unter OS X und Linux zu verwenden, ohne Sicherungsdateien zu erstellen. Also habe ich stattdessen diesen Ruby-Einzeiler verwendet, um dies zu tun:

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

In meinem Fall musste ich sie von einer rake Task (d.h. innerhalb eines Ruby-Skripts), daher habe ich diese zusätzliche Ebene der Anführungszeichen verwendet:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X