複数行のテキストファイル内で複数行のテキストファイルを1つ見つけて置き換える

複数行のテキストファイル内で複数行のテキストファイルを1つ見つけて置き換える

私は長い間その問題に苦しんでいましたが、今は完全にアイデアはありません。たぶんここで誰かが私を助けることができます。これが私が達成したいものです:

file_1.txt:

# Some comment
some_variable="test"
some other things

# Marker

More things!@#$%^

file_2.txt:

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

代わりfile_2.txtにに挿入して後でプロセスを元に戻したいと思います。file_1.txt# Marker

最終文書file_1.txt:

# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

More things!@#$%^

問題は、両方のファイルが複数行になっており、さまざまな特殊文字が含まれていることです。また、これら2つのファイルを変数に入れたいと思います。

私はsed、Perl、awkなど様々なものを試しました。私には何も効果がありません。私はこれが私の最も近い試みだと思います。

perl -pi -e 'chomp if eof' file_2.txt
marker_var="# Marker"
file_2_var=$(tr '\n' '\f' <file_2.txt)

sed -e "s|$marker_var|$file_2_var| tr '\f' '\n'" file_1.txt

まだ動作していないので、最も近いと言います。 stackexchangeのさまざまな答えを組み合わせてみましたが、正しく終了しないというエラーが発生しますs。私はファイルの最後の新しい行が原因であると思われ、\nperlコマンドを使用して削除しようとしましたが、うまくいきませんでした。

誰でも私を助けることができますか?

答え1

すでにPerlがある場合は、Perlを実行してください。

open(f1,"<file_1.txt");
open(f2,"<file_2.txt");
open(out,">new_file_1.txt");

while(<f1>) {
   last if /# Marker/;
   print out;
}
print out while(<f2>);
print out while(<f1>);

close(out);
close(f1);
close(f2);

答え2

awkを使ってファイルをマージするのは本当に簡単です。

awk 'NR==FNR {if ($1 == "#" && $2 == "Marker") while((getline a<ARGV[2]) > 0) print a; else print}' file_1.txt file_2.txt > out
  • NR==FNRこれは最初のファイルでのみ機能する奇妙なトリックです。これを確認してくださいより多くの情報が必要な場合は答えてくださいNRとFNRについて
  • {if ($1 == "#" && $2 == "Marker")else print}# Marker: 最初のファイルを解析し、すべての行を出力します。いいえ確立された。
  • while((getline a<ARGV[2]) > 0) print a;ARGV[2] (ここでは file_2.txt) の内容を解析して出力します。
  • > outこれはシェルリダイレクトで、このコマンドの出力をoutファイルに書き込みます(ファイルがない場合はファイルを生成します)。

結果:

$ awk 'NR==FNR {if ($1 == "#" && $2 == "Marker") while((getline a<ARGV[2]) > 0) print a; else print}' file_1.txt file_2.txt
# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

More things!@#$%^

答え3

使用sed

$ sed -Ee '/Marker/{e cat file_2.txt' -e ';d}' file_1.txt
# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"


More things!@#$%^

答え4

awkを使用してください。

$ awk 'NR==FNR{new=new sep $0; sep=ORS; next} /# Marker/{$0=new} 1' file_2.txt file_1.txt
# Some comment
some_variable="test"
some other things

# Marker
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

More things!@#$%^

$ awk 'NR==FNR{new=new sep $0; sep=ORS; next} /# Marker/{$0=new} 1' file_1.txt file_2.txt
# Some comment
some_variable="test"
some other things

# Marker

More things!@#$%^
# Some other comment
other_variable_1="test"

# Some totally other comment
other_variable_2="test"

あなたの質問のスクリプトについて:

  1. これを行うと、tr '\n' '\f'必要な終了改行文字が含まれなくなり、有効なテキストファイルがなくなり、YMMVsedまたは他のテキスト処理ツールがそれを処理します。
  2. 入力にフォームフィードが含まれている場合、改行をフォームフィードにマップするプロセスは失敗します。これは、印刷(または他の同様のテキスト)時に新しいページの上部で関数が開始されるように強制したいコードの関数間で使用されるのと同じです。印刷すると、特定の場所にページが表示されます。)
  3. sed -e "s|$marker_var|$file_2_var|独自にsまたは逆参照をfile_2_var含めることができるため、これを行うことはできません|。たとえば、&sedは\1これを解釈します。https://stackoverflow.com/q/29613304/1745001

関連情報