Comment insert des lignes avec des numéros de X à Y dans un autre file après la ligne Z?

J'ai créé deux files:

echo -e "1\n2\n3\n4\n5" > 123.txt echo -e "a\nb\nc\nd\ne" > abc.txt 

Je veux get le file 123.txt avec le contenu suivant:

 1 2 3 b c d 4 5 

Donc, en d'autres termes, insérez les lignes avec des nombres de 2 à 4 du file abc.txt dans le file 123.txt après la troisième ligne.

J'ai examiné les nombreuses questions similaires ici, mais je n'ai pas trouvé de réponse appropriée. Néanless j'ai eu les lignes:

 sed -n '2,4p' abc.txt 

et mettre du text dans le file après la troisième ligne:

 sed -i '3a\mytext' 123.txt 

Comment faire cela en utilisant la command précédente stdout ou / et une command unique sed / awk ?

Si votre système possède la version GNU de sed , vous pouvez utiliser la command GNU extension 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. 

Par exemple,

 $ sed '3r /dev/stdin' 123.txt < <(sed -n '2,4p' abc.txt) 1 2 3 b c d 4 5 

En utilisant awk et sed :

 $ awk 'FNR==3{print;system("sed -n '2,4p' abc.txt");next};1' 123.txt 1 2 3 b c d 4 5 

Avec sed , vous pouvez utiliser la command r pour insert un file entier. Pour insert une partie d'un file, extrayez cette partie et envoyez-la en input à sed . Vous pouvez utiliser sed pour faire l'extraction aussi.

 sed -n '2,4p' abc.txt | sed -i '3r /dev/stdin' 123.txt 

Avec awk , vous pouvez lire un file et passer à un autre file au milieu.

 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 

Vous pouvez également utiliser la head et la tail pour extraire les parties des files que vous souhaitez combiner.

 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 

Vous pouvez combiner l'approche head + tail avec sed . Pour les files volumineux, il est probable que ce soit le plus rapide.

 <abc.txt tail -n +2 | head -n 3 | sed -i '3r /dev/stdin' 123.txt 

Notez que toutes ces approches écrivent dans un file temporaire qui est déplacé vers 123.txt (même les approches utilisant sed -i , parce que c'est ce que sed -i fait sous le capot).

Modification en place à l'aide de ed et sed (à l'invite bash):

 ed -s 123.txt<<<$'3r !sed -n "2,4p" abc.txt\nw'