tl;dr :
macOSにもあるようなBSD Sedでは、コマンドを機能させるために (バックアップ ファイルを作成しないために)の代わりに使用する必要があります。例えば:-i ''
-i
sed -i '' 's/RABBITMQ_HOST=.*/RABBITMQ_HOST='"$RABBITMQ_HOST"'/' "$Deploy_path"
コマンドをGNU と BSD Sedの両方で動作させるには、空でないオプション引数(バックアップを作成する) を指定し、それを直接に添付します-i
。
sed -i'.bak' 's/RABBITMQ_HOST=.*/RABBITMQ_HOST='"$RABBITMQ_HOST"'/' "$Deploy_path" &&
rm "$Deploy_path.bak" # remove unneeded backup copy
背景情報、(より) ポータブルなソリューション、およびコマンドの改良については、以下を参照してください。
オプションの背景情報
BSD/macOS を使用しているようです。sed
その-i
オプションには、作成するバックアップ ファイルのサフィックスを指定するオプション引数が必要です。
したがって、(予想に反して)のオプション引数(バックアップ接尾辞) として解釈されるのはスクリプトであり、入力sed
ファイル名はscriptとして解釈され、明らかに失敗します。-i
対照的に、コマンドはGNU sed
構文を使用します。ここでは、入力ファイルのバックアップ ファイルをインプレースで更新しない-i
ことを示すために単独で使用できます。
同等のBSD sed
オプションは次のとおりです - option-argument を指定するために別の引数を使用する技術的な-i ''
必要性に注意してください。これは空の文字列であるためです ( を使用した場合、シェルはそれを見る前に単純に削除します:は事実上、単に)。 ''
-i''
''
sed
-i''
-i
悲しいことに、これはGNU では機能しません。これは、に直接接続されsed
ている場合にのみオプション引数を認識し、別の引数を別の引数、つまりscriptとして解釈するためです。-i
''
この動作の違いは、オプションの実装の背後にある根本的に異なる設計上の決定に起因しており-i
、下位互換性のためにおそらくなくなることはありません。[1]
バックアップ ファイルを作成したくない場合、 BSD と GNUの両方で機能する単一の-i
構文はありません。sed
4 つの基本的なオプションがあります。
(a) GNUまたはBSDのいずれかのみを使用することがわかっている場合は、それに応じてオプションを構成します: GNU用、BSD 用。sed
-i
-i
sed
-i ''
sed
(b)のオプション引数として空でない接尾辞を指定します。これを直接オプションに付けると、両方の実装で機能-i
します。例: 。これにより、必ずサフィックス のバックアップ ファイルが作成されますが、後で削除することもできます。-i
-i'.bak'
.bak
(c)sed
処理している実装を実行時に決定し、それに応じてオプションを構築し-i
ます。
(d) -i
(これは POSIX に準拠していません) を完全に省略し、成功時に元のファイルを置き換える一時ファイルを使用します: sed '...' "$Deploy_path" > tmp.out && mv tmp.out "$Deploy_path"
.
これは本質的-i
に舞台裏で行われることであり、予期しない副作用を引き起こす可能性があることに注意してください。特に、シンボリックリンクである入力ファイルが通常のファイルに置き換えられます。-i
、ただし、元のファイルの特定の属性を保持します。この私の回答の下半分を参照してください。
bash
元のコード (2 つの置換による単一の呼び出し) を簡素化し、より堅牢にする (c)の実装を次に示しsed
ます (変数は二重引用符で囲みます)。
#!/bin/bash
RABBITMQ_HOST='rabbitmq1'
RABBITMQ_PASS='12345'
Deploy_path="test.env"
# Construct the Sed-implementation-specific -i option-argument.
# Caveat: The assumption is that if the `sed` is not GNU Sed, it is BSD Sed,
# but there are Sed implementations that don't support -i at all,
# because, as Steven Penny points out, -i is not part of POSIX.
suffixArg=()
sed --version 2>/dev/null | grep -q GNU || suffixArg=( '' )
sed -i "${suffixArg[@]}" '
s/^\(RABBITMQ_HOST\)=.*/\1='"$RABBITMQ_HOST"'/
s/^\(RABBITMQ_PASS\)=.*/\1='"$RABBITMQ_PASS"'/
' "$Deploy_path"
$RABBITMQ_HOST
上でおよびに対して定義された特定の値を使用して、それらをスクリプトに$RABBITMQ_PASS
直接スプライスしても安全ですが、値に、、、または改行のインスタンスが含まれている場合は、コマンドを壊さないように事前にエスケープする必要があります。一般的なプリエスケープを実行する方法については、私のこの回答を
参照してください。sed
&
/
\
sed
awk
perl
[1] GNU Sed は -i のオプション引数をオプションと見なしますが、BSD Sed は必須と見なします。これは構文仕様にも反映されています。それぞれのman
ページ: GNU Sed: -i[SUFFIX]
vs. BSD Sed -i extension
.