sed
文字列置換キーワードを使用するには、sed
置換文字列を解釈してください。代替文字列にsed
特殊と見なされる文字(charなど)が含まれている場合、何をすべきかを示す文字が/
代替文字列に含まれたくない限り失敗します。sed
前任者:
VAR="hi/"
sed "s/KEYWORD/$VAR/g" somefile
sed
特殊文字を解釈しないように代替文字列を指示する方法はありますか?私が望むのは、内容が何であれ、ファイルのキーワードを変数の内容に置き換えることができることです。
答え1
置換部分には4つの特殊文字しかありません:\、、 &改行、区切り記号(引用する)
$ VAR='abc/def&ghi\foo
next line'
$ repl=$(sed -e 's/[&\\/]/\\&/g; s/$/\\/' -e '$s/\\$//' <<<"$VAR")
$ echo "$repl"
abc\/def\&ghi\\foo\
next line
$ echo ZYX | sed "s/Y/$repl/g"
Zabc/def&ghi\foo
next lineX
答え2
-p
sed(ループ入力仮定)と-e
(コマンドラインにプログラムを提供する)の代わりにPerlを使用できます。 Perlを使用すると、環境変数にアクセスできます。いいえこれをシェルに挿入します。この変数は次のようにする必要があります。出口:
export VAR='hi/'
perl -p -e 's/KEYWORD/$ENV{VAR}/g' somefile
変数をどこにでもエクスポートしたくない場合は、プロセスに提供してください。
PATTERN="$VAR" perl -p -e 's/KEYWORD/$ENV{PATTERN}/g' somefile
Perlの正規表現の構文は、基本的にsedの構文とは少し異なります。
答え3
ほとんどの変数値を正しく処理する最も簡単な解決策は、印刷されない文字を代替コマンドsed
の区切り文字として使用することです。
vi
多くのシェルでは、^V
Ctrl-V(通常は作成)を入力してすべての制御文字をエスケープできます。したがって、一部の制御文字(^A
この場合は区切り文字として頻繁に使用されます)を使用している場合、sed
その非印刷文字が入力した変数に存在する場合にのみコマンドが中断されます。
したがって、シェル"s^V^AKEYWORD^V^A$VAR^V^Ag"
に入力する内容はvi
次のとおりです。
sed "s^AKEYWORD^A$VAR^Ag" somefile
(この回答はコピーして貼り付けることはできません。実際に説明どおりに入力する必要があります。)
$VAR
これは、印刷できない文字が含まれていない限り機能します^A
。その可能性はほとんどありません。
もちろん合格すればユーザー入力value$VAR
の場合、すべての賭けがキャンセルされ、通常のユーザーが入力するのが難しい制御文字に依存するよりも、入力を完全にクリーンアップする方が良いです。
しかし、実際には区切り文字列よりも注目すべき点が多くあります。たとえば、&
代替文字列に表示される場合は、「テキスト全体が一致します」を意味します。たとえば、s/stu../my&/
「stuff」を「mystuff」に変更し、「stung」を「mystung」に変更します。だから、どの文字を置換文字列として変数に入れたいのですが、その変数のリテラル値のみを使用したい場合は、その変数をから文字列として使用する前にいくつかのデータをクリーンアップする必要がありますsed
。 (ただし、データクリーニングも可能ですsed
。)
答え4
行ベースで、置き換える行が1つしかない場合は、ファイル自体の前に交換行を追加し、printf
最初の行を予約済みsed
スペースに保存してから必要に応じて挿入することをお勧めします。これにより、特殊文字についてまったく心配する必要はありません。 (ここで唯一の仮定は、改行$VAR
なしでテキスト行を含めることですが、これはあなたの意見で述べたものです。)改行に加えて、VARには次のものが含まれます。何もないとにかくこれはうまくいきます。
VAR=whatever
{ printf '%s\n' "$VAR";cat somefile; } | sed '1{h;d;};/KEYWORD/g'
printf '%s\n'
$VAR
内容に関係なくリテラル文字列として印刷され、その後に改行文字が続きます。 (echo
場合によっては他の操作が実行されます。たとえば、内容が$VAR
ハイフンで始まると、に渡されたオプションフラグとして解釈されますecho
。)
printf
中括弧は、に渡されたコンテンツの出力の前に追加するために使用されます。ここでは、閉じ括弧の前のセミコロンと同様に、中括弧自体を区切るスペースが重要です。somefile
sed
1{h;d;};
コマンドはsed
テキストの最初の行をsed
's'に保存します。スペアスペースを押してからd
行を削除します(印刷するのではなく)。
/KEYWORD/
含まれるすべての行に次の操作を適用しますKEYWORD
。ジョブはg
etであり、予約されたスペースの内容を取得して次に置き換えます。パターン空間- つまり、現在の行全体です。 (単に交換のみのためのものではありません。部分しかし、予約されたスペースは消去されません。コピーパターン空間に入り、その中にあるすべてを変えます。
欲しいならアンカー正規表現なので一致しません。含むKEYWORDなのに1行だけあり、KEYWORD以外には何もありません。^
正規表現に最初の行基準点()と終了行基準点()を追加します。$
VAR=whatever
{ printf '%s\n' "$VAR";cat somefile; } | sed '1{h;d;};/^KEYWORD$/g'