テキストファイル内のマーカーを任意の新しいテキストに置き換える

テキストファイル内のマーカーを任意の新しいテキストに置き換える

テキストと、新しいコンテンツを追加する場所を示すマーカーが1行に書かれたファイルがあります。

foo
bar
%SUBSTITUTE%
foo

行の置換は、新しい複数行の文字列に置き換えられますtext="some text"(文字列がわからないことに注意してください。たとえば、text=cat "file"`` というファイルを読み込んだ結果である可能性があります)。置換の結果は次のようになります。

foo
bar
some text
%SUBSTITUTE%
foo

以前動作していたバージョンがperl動作しなくなりました (どうやら perl バージョンの変更によるものと思われます)。現在、 や などの標準ユーティリティを使用して行を置き換えようとしていますtrsed貼り付ける文字列にバックスラッシュなどの任意の文字が含まれている可能性があるため、問題が発生しています。貼り付ける前にこれらをエスケープしたくありません。

標準ツールで機能する安全な方法はありますか? この問題に関して私が見つけた他の疑問は、貼り付けるテキストがわかっている特定の解決策です。

答え1

rGNU版のsedをお持ちの場合は、コマンドを使用してファイルから新しいコンテンツを読み込んで挿入し、マーカー行を削除できるはずです。例:

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%、新しいコンテンツをcatで挿入することができます。

csplit -s file '/%SUBSTITUTE%/'
cat xx00 newcontent xx01

また、最初のファイルの行に対して bashreadループを実行し、マーカー文字列に一致したときに新しいコンテンツ ファイルを cat することもできます。ただし、このフォーラムでテキスト処理に読み取りループを提案したことで、私は非難されました。残念ながら、どちらもインプレース ソリューションを提供していません。

答え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%。この文字列の利点は、ファイルに保存し直す必要がなく、さまざまなシェル ツールを使用してこの文字列を操作できることです。環境変数から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)。

関連情報