web-dev-qa-db-fra.com

SED: copier les lignes d'un fichier sur une ligne spécifique d'un autre fichier

Je peux le faire en utilisant l'exemple suivant. La 1ère commande affichera les lignes 16 à 80 du file1 à patch, tandis que la 2ème insérera le contenu de patch après la ligne 18 dans file2:

sed -n 16,80p file1>patch
sed -i 18rpatch file2

Cependant, je voudrais copier directement d'un fichier à un autre sans utiliser de fichier temporaire intermédiaire, dans une commande utilisant sed (pas awk, etc.). Je suis sûr que c'est possible, mais je ne sais pas comment.

5
mYself

Faire cela avec sed nécessite quelques ruses supplémentaires de Shell. En supposant que Bash, vous pourriez utiliser

sed -i 18r<(sed '16,80!d' file1) file2

<(sed '16,80!d' file1) est remplacé par le nom d'un tuyau à partir duquel la sortie de sed '16,80!d' file1 peut être lue.

En général, j'estime qu'il est plus agréable de faire cela avec awk (même un peu plus longtemps), car awk est mieux équipé pour gérer plusieurs fichiers d'entrée. Par exemple:

awk 'NR == FNR { if(FNR >= 16 && FNR <= 80) { patch = patch $0 ORS }; next } FNR == 18 { $0 = patch $0 } 1' file1 file2

Cela fonctionne comme suit:

NR == FNR {                       # While processing the first file
  if(FNR >= 16 && FNR <= 80) {    # remember the patch lines
    patch = patch $0 ORS
  }
  next                            # and do nothing else
}
FNR == 18 {                       # after that, while processing the first file:
  $0 = patch $0                   # prepend the patch to line 18
}
1                                 # and print regardless of whether the current
                                  # line was patched.

Cependant, cette approche ne se prête pas à l’édition sur place de fichiers. Ce n'est généralement pas un problème. J'utiliserais simplement

cp file2 file2~
awk ... file1 file2~ > file2

avec l'avantage supplémentaire d'avoir une sauvegarde au cas où les choses tournent en forme de poire, mais à la fin, c'est vous qui décidez.

5
Wintermute

J'ai fait quelque chose de similaire en utilisant:

    head -80 file | tail -16 > patch

Consultez la documentation de vos versions locales de head et tail et modifiez les deux nombres entiers selon vos besoins.

3
Arif Burhan

j'ai eu ce problème, je l'ai fait en 2 étapes (1-tail 2-head), par exemple dans un fichier texte de 20 lignes (test.txt), nous voulons copier les lignes de 13 à 17 dans un autre fichier (final. SMS),

tail -8 test.txt> temp.txt
head -5 temp.txt> final.txt

0
Farshad Falaki
sed -i '1,15 d
        34 r patch
        81,$ d' YourFile

# oneliner version
sed -i -e '1,15 d' -e '34 r patch' -e '81,$ d' YourFile
  • ordre de ligne n'est pas important.
  • Vous pouvez adapter un bit ou le grouper avec une variable comme celle-ci

sed -i "1,16 d $(( 16 + 18 )) r patch 81,$ d" YourFile

mais ajouter une certaine sécurité sur le nombre de lignes dans ce cas.

  • si la ligne r est supérieure à une ligne, les lignes suivantes sont toujours comptées à partir de l'emplacement d'origine et le fichier final est supérieur à 80 - 16 lignes.

je ne teste pas exactement la ligne prise, exclue ou modifiée (comme 34 est la 18ème ligne du fichier recadré), mais le principe est le même.

Explication des références d'index de lignes utilisées dans cet exemple:

  • 1,15 est la ligne de titre à supprimer, le fichier prend donc des lignes de soin à partir de 16 dans ce cas.
  • 34 est la ligne pour changer le contenu et est le résultat de la 18ème ligne APRÈS le premier nouveau contenu (ligne 16 dans notre cas) donc 16 + 18 = 34
  • 81,$ sont des lignes de fin à supprimer, $ signifie la dernière ligne et 81 est la première ligne (après la prise de 80) des lignes de fin non désirées.
0
NeronLeVelu