一部のテキストと新しいコンテンツを追加する場所を示すマークが1行に含まれるファイルがあります。
foo
bar
%SUBSTITUTE%
foo
1行ずつ置き換えるものは、新しい複数行の文字列で置き換える必要がありますtext="some text"
(文字列がわからないことに注意してください。たとえば、cat "file"ファイルを読み取った結果ですtext=
)。代替結果は次のようになります。
foo
bar
some text
%SUBSTITUTE%
foo
動作が停止した作業バージョンがありましたperl
(明らかにPerlバージョンの変更により)。これで、tr
同じ標準ユーティリティを使用してその行をsed
置き換えようとしています。貼り付ける文字列にバックスラッシュなどの任意の文字を含めることができるため、問題が発生しました。貼り付ける前にこれらの文字をエスケープしたくありません。
標準ツールを使用してこれを行う安全な方法はありますか?この問題について私が見つけた他の問題は、貼り付けられていることが知られているテキストの特定の解決策です。
答え1
sedのGNUバージョンがある場合は、そのr
コマンドを使用してファイルから読み取り、新しい内容を挿入してから、表示された行を削除できます。
sed '/%SUBSTITUTE%/{
r path/to/newcontent
d
}' file
%SUBSTITUTE%
タグを維持したい場合後ろに挿入してください。何をしても、GNUr
拡張はファイルの内容をキューに入れるので難しいです。終わり現在のモード周期(継続)今後コマンドを削除するだけですd
。)おそらく最も簡単な方法はファイルに追加することですnewcontent
。次のようにすぐに実行できます。
sed '/%SUBSTITUTE%/{
r /dev/stdin
d
}' file < <(sed '$a %SUBSTITUTE%' path/to/newcontent)
まったく異なるアプローチを使用すると、最初のファイルを分割し%SUBSTITUTE%
て新しいコンテンツを追加できます。
csplit -s file '/%SUBSTITUTE%/'
cat xx00 newcontent xx01
最初のファイルの行に対してbashループを実行し、タグ文字列が一致したときに新しいファイルの内容をキャプチャすることもできますread
。しかし、このフォーラムで提案されているように、テキスト処理のためのループを読むことはすでに不安です。残念ながら、どちらも適切な解決策を提供しません。
答え2
これを使用する別の方法がありますed
。タグの前に挿入されたすべての項目
(つまり、含む行の前):FILE
%SUBSTITUTE%
ed -s originalfile <<< $'/%SUBSTITUTE%/- r FILE\nw\nq'
ここで::
/%SUBSTITUTE%/
一致する最初の行にアドレスを設定する%SUBSTITUTE%
-
か:-1
1行前のアドレスをオフセットします。 ::書き込み(書き込みの代わりにコンテンツを印刷することに置き換えられます):エディタの終了
r FILE
Reads FILE to after the addressed line.
w
originalfile
,p
q
FILE
タグの前に!echo "$TEXT"
挿入する項目に置き換えます。$TEXT
export TEXT
ed -s originalfile <<'IN'
/%SUBSTITUTE%/-1 r !echo "$TEXT"
w
q
IN
答え3
私は以下に基づいて解決策を見つけましたawk
。
text=`cat "filepaste"`
export text;
<"$file" awk '
BEGIN {REPLACE=ENVIRON["text"] "\n%SUBSTITUTE%" }
{gsub(/^%SUBSTITUTE%$/, REPLACE); print}
'
ここで、「filepaste」には置き換えるコンテンツが含まれています%SUBSTITUTE%
。 1つの利点は、文字列をファイルに保存しなくても、さまざまなシェルツールを使用して文字列を操作できることです。環境変数からawk
変数を読み取ると、拡張REPLACE
時にエスケープ文字が防止されますtext
。
答え4
これでPerlソリューションがあるので、ここに別のソリューションがあります。私はrep.txt
交換品を保存するために使用します。
$ perl -pe '$re=`cat rep.txt`; chomp($re); s/%SUBSTITUTE%\n/$re/' file.txt
foo
bar
multi
line
string
foo
ターゲットファイルの各行を読み取り(file.txt
)、与えられたスクリプトを-e
ここに適用して印刷します(-p
)。