別のファイルのパターン(タグ)の前にあるファイルの内容を挿入するには?

別のファイルのパターン(タグ)の前にあるファイルの内容を挿入するには?

File1コンテンツ:

line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 

File2コンテンツ:

line1-file2     "25"  
line2-file2     "24"  
Pointer-file2   "23"  
line4-file2     "22" 
line5-file2     "21"

Perl/shell スクリプトが実行された後、File2内容は次のようになります。

line1-file2     "25"  
line2-file2     "24" 
line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 
Pointer-file2   "23" 
line4-file2     "22" 
line5-file2     "21"

File1つまり、File2「Pointer」を含む行の前にinの内容を貼り付けます。

答え1

このsedユーティリティには修正操作を実行する機能があります。

sed -i -e '/Pointer/r file1' file2

しかし、これはあなたをコンテンツの上の行ですfile1。簡単に言えば、遅延ライン出力です。

sed -n -i -e '/Pointer/r file1' -e 1x -e '2,${x;p}' -e '${x;p}' file2 

GNUの使用sed:

sed '/Pointer/e cat file1' file2

~によると手動のためe [command]

rコマンドとは異なり、このコマンドの出力はすぐに印刷されます。 r コマンドは、現在の期間が終了するまで出力を遅延します。

答え2

sedまたはを使用しないでくださいawk

まず、パターンのある行を見つけます。

line=$(grep -n 'Pointer' file2 | cut -d ":" -f 1)

次に、3つのコマンドを使用して目的の結果を出力します。

{ head -n $(($line-1)) file2; cat file1; tail -n +$line file2; } > new_file

これは3回訪問する必要があるという欠点がありますが、解決策file2よりもきれいになります。sedawk

答え3

awkこれをかなり簡単にします。
ファイルの前に次の行を挿入します。

awk '/Pointer/{while(getline line<"innerfile"){print line}} //' outerfile >tmp
mv tmp outerfile

その行の後に内部ファイルを印刷するにはPointerモード順序を切り替え(デフォルトの動作を得るにはセミコロンを追加する必要があります)、変数を削除できますline

awk '//; /Pointer/{while(getline<"innerfile"){print}}' outerfile >tmp
mv tmp outerfile

まだ誰も使用していないのでperl

# insert file before line
perl -e 'while(<>){if($_=~/Pointer/){system("cat innerfile")};print}' outerfile

# after line
perl -e 'while(<>){print;if($_=~/Pointer/){system("cat innerfile")}}' outerfile

答え4

簡単な作業ed

ed -s file1 <<IN
/Pointer/-r file2
,p
q
IN

-r file1指定されたファイルを指定された行に読み取った後、この場合、最初の行より前の行が一致しますPointer。したがって、複数行に表示されてもfile2コンテンツは一度だけ挿入されます。Pointer一致する各行の前に挿入するには、gグローバルフラグを追加します。

ed -s file1 <<IN
g/Pointer/-r file2
,p
q
IN

ファイルをその場所で編集するには、,pに置き換えます。w


許可されたsed回答はほとんどの場合機能しますが、マーカーが最後の行にある場合、コマンドは期待どおりに機能しません。つまり、File1マーカーの後にコンテンツが挿入されます。
私は最初に次のことを試しました。

sed '/Pointer/{r file1
N}' file2

また、うまく機能しますが(ループrの最後で魔法が機能するように)、マーカーがN最後の行にある場合(最後の行の後に分岐がない場合)、同じ問題が発生します。この問題を解決するには、入力に改行文字を追加するだけです。

sed '/Pointer/{              # like the first one, but this time even if the
r file1                      # marker is on the last line in File2 it
N                            # will be on the second to last line in
}                            # the combined input so N will always work;
${                           # on the last line of input: if the line is
/^$/!{                       # not empty, it means the marker was on the last
s/\n$//                      # line in File2 so the final empty line in the
}                            # input was pulled i\n: remove the latter;
//d                          # if the line is empty, delete it
}' file2 <(printf %s\\n)

file2一致する各行の前に内容が挿入されます。一致する最初の行の前にのみ挿入するには、oopを使用してファイルの終わりに達するまで次の行をl引きます。n

sed '/Pointer/{
r file2
N
:l
$!n
$!bl
}
${
/^$/!{
s/\n$//
}
//d
}' file1 <(printf %s\\n)

これらのsedソリューションを使用すると、所定の場所で編集する機能が失われます(ただし、別のファイルにリダイレクトすることはできます)。

関連情報