私は2つのファイルを作成しました。
echo -e "1\n2\n3\n4\n5" > 123.txt
echo -e "a\nb\nc\nd\ne" > abc.txt
123.txt
以下を含むファイルを取得したいと思います。
1
2
3
b
c
d
4
5
つまり、abc.txt
ファイルの3行目の後にファイルの2〜4行を挿入します123.txt
。
ここで同様の質問をたくさん見ましたが、適切な答えが見つかりませんでした。それでも、次のような行があります。
sed -n '2,4p' abc.txt
ファイルの3行目の後にテキストを入力してください。
sed -i '3a\mytext' 123.txt
以前のコマンドstdoutまたは/and sed
/単一のコマンドを使用してawk
これをどのように実行できますか?
答え1
システムにGNUバージョンがある場合は、sed
GNU拡張コマンドを使用できますr
。
r filename
As a GNU extension, this command accepts two addresses.
Queue the contents of filename to be read and inserted into the
output stream at the end of the current cycle, or when the next input
line is read. Note that if filename cannot be read, it is treated as
if it were an empty file, without any error indication.
As a GNU sed extension, the special value /dev/stdin is supported for
the file name, which reads the contents of the standard input.
例えば、
$ sed '3r /dev/stdin' 123.txt < <(sed -n '2,4p' abc.txt)
1
2
3
b
c
d
4
5
答え2
awk
とを使用してsed
:
$ awk 'FNR==3{print;system("sed -n '2,4p' abc.txt");next};1' 123.txt
1
2
3
b
c
d
4
5
答え3
Passを使用するsed
と、このr
コマンドを使用してファイル全体を挿入できます。ファイルの一部を挿入するには、その部分を抽出して入力にパイプすることもできますsed
。sed
sed -n '2,4p' abc.txt | sed -i '3r /dev/stdin' 123.txt
を使用すると、awk
あるファイルを読み取り、途中で別のファイルに切り替えることができます。
awk <123.txt >123.txt.new '
1 # print the input line
NR==3 { # after line 3 of 123.txt, …
while (getline < "abc.txt") {
++inner_NR;
if (inner_NR >= 2) print; # start printing at line 2 from abc.txt
if (inner_NR == 4) break; # stop after line 4
}
}
' &&
mv 123.txt.new 123.txt
マージしたいファイルの部分を抽出するためにおよびhead
を使用することもできます。tail
head -n 3 <123.txt >123.txt.new &&
<abc.txt tail -n +2 | head -n 3 >>123.txt.new &&
tail -n +4 123.txt >>123.txt.new &&
mv 123.txt.new 123.txt
head
+tail
メソッドとを組み合わせることができますsed
。大容量ファイルの場合、この方法はおそらく最速です。
<abc.txt tail -n +2 | head -n 3 | sed -i '3r /dev/stdin' 123.txt
これらのメソッドはすべて移動された一時ファイルに書き込まれます123.txt
(使用されているメソッドも同じです。これは後ろに起こるためsed -i
です)。sed -i
答え4
ed
内部編集に使用しますsed
(bashプロンプトで):
ed -s 123.txt<<<$'3r !sed -n "2,4p" abc.txt\nw'