web-dev-qa-db-ja.com

-iオプション付きのsedコマンドはMacでは失敗しますが、Linuxでは動作します

Linuxでテキストを検索/置換するために、次のsedコマンドを使用しました。

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

しかし、私は私のMac OS X上でそれを試してみると、私は得る:

"コマンドcは\の後にテキストが続くことを想定しています"

私のMacは普通のBASHシェルを実行していると思いました。どうしたの?

編集:

@ High Performanceによると、これはMacのsedが異なる(BSD)フレーバーであるためです。したがって、私の質問はBSD sedでこのコマンドをどのように複製するのかということです。

編集:

これを引き起こす実際の例はここにあります:

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

-iオプションを使用する場合は、バックアップの拡張子を指定する必要があります。

あなたが持っている場合:

File1.txt
File2.cfg

コマンド(新しいバージョンのMacとGNUで動作するようにするには、-i''および-eの間にスペースがないことに注意してください)。

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

次のように2つのバックアップファイルを作成します。

File1.txt.original
File2.cfg.original

すべての場合に有効なsedコマンドの組み合わせを見つけることは不可能であるため、バックアップファイルを作成することを避けるための移植性のある方法はありません。

  • sed -i -e ... - -eバックアップを作成するため、OS Xでは機能しません
  • sed -i'' -e ... - OS X 10.6では動作しませんが10.9以降で動作します
  • sed -i '' -e ... - GNUに取り組んでいない

すべてのプラットフォームで機能するsedコマンドがあるわけではないので、別のコマンドを使用して同じ結果を得ることができます。

例:Perl -i -pe's/old_link/new_link/g' *

335
Sinetris

私はあなたがバックアップファイルのための拡張子-iを使うとき、私はOS Xを信じています必須。試してください:

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

GNU sedを使用すると、拡張子はオプションになります。

48

これはGNUとBSDの両方のsedで動作します。

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

またはバックアップ付き:

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

-iオプションの後にスペースがないことに注意してください。 (GNU sedに必要)

48
chipiik

Macでも同じ問題があり、brewで解決しました。

brew install gnu-sed

そしてとして使用

gsed SED_COMMAND

sedgsedのエイリアスとして設定することもできます(必要な場合)。

alias sed=gsed
24
Sruthi Poddutur

または、gsedというGNUバージョンのsedをMacにインストールして、標準のLinux構文を使用して使用することもできます。

そのためには、gsedをportsを使ってインストールします(持っていないのなら、Sudo port install gsedを実行して http://www.macports.org/ で入手してください)。その後、sed -i 's/old_link/new_link/g' *を実行できます。

17
Ohad Kravchick

あなたのMacは確かにBASHシェルを走らせています、しかしこれはあなたが扱っているsedのどの実装のもっと問題です。 Macでは、sedはBSDから来ており、典型的なLinuxマシンで見られるsedとは微妙に異なります。私はあなたにman sedを勧めます。

Sinetrisの答えは正しいですが、私はこれをfindコマンドと共に使用して、変更したいファイルについてより具体的にします。一般にこれはうまくいくはずです(osx /bin/bashでテスト済み):

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

一般に、複雑なプロジェクトでsedを指定せずにfindを使用すると、効率が悪くなります。

8
Lucas

環境変数をテンプレートファイルに適用する方法は次のとおりです(バックアップは不要)。

1.後で置き換えられるように{{FOO}}でテンプレートを作成します。

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

2. {{FOO}}をFOO変数に置き換えて、新しいfoo.confファイルに出力します。

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

macOS 10.12.4buntu 14.04.5の両方を動作させる

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

BSDとLinuxの両方で動作します

0
ashokrajar

他の答えが示すように、バックアップファイルを作成せずにOS XとLinuxの間でsedを使い分ける方法はありません。そのため、私は代わりにこのRubyのワンライナーを使用しました。

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

私の場合は、rakeタスクから(つまり、Rubyスクリプト内で)それを呼び出す必要があったので、この追加レベルの引用を使用しました。

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

私は、MacOS(MacOS 10.12でテスト済み)と他のOSとの間のsedの違いを処理するための関数を作成しました。

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
}

使用法:

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

どこで:

,は区切り文字です

's,MASTER_Host.*,MASTER_Host='"$MASTER_IP"','はパターンです

"./mysql/.env"はファイルへのパスです

0
v.babak