Remplacer le texte entre deux chaînes dans un fichier en utilisant linux bash

J’ai le fichier “acl.txt”

192.168.0.1 192.168.4.5 #start_exceptions 192.168.3.34 192.168.6.78 #end_exceptions 192.168.5.55 

et un autre fichier “exceptions”

  192.168.88.88 192.168.76.6 

Je dois tout remplacer entre #start_exceptions et #end_exceptions avec le contenu du fichier d’exceptions. J’ai essayé beaucoup de solutions de ce forum mais aucune ne fonctionne.

EDITED :

Ok, si vous voulez conserver #start et #stop, je reviens à awk:

 awk ' BEGIN {p=1} /^#start/ {print;system("cat exceptions");p=0} /^#end/ {p=1} p' acl.txt 

Merci à @fedorqui pour les modifications dans les commentaires ci-dessous.

Sortie:

 192.168.0.1 192.168.4.5 #start_exceptions 192.168.88.88 192.168.76.6 #end_exceptions 192.168.5.55 

p est un drapeau qui indique s’il faut ou non imprimer des lignes. Il commence au début par 1, donc toutes les lignes sont imprimées jusqu’à ce que je trouve une ligne commençant par #start. Ensuite, je fouille le contenu du fichier d’exceptions et arrête d’imprimer les lignes jusqu’à ce que je trouve une ligne commençant par #end, auquel cas je ramène le drapeau p à 1 pour que les lignes restantes soient imprimées.

Si vous voulez une sortie dans un fichier, ajoutez “> newfile” à la toute fin de la commande comme ceci:

 awk ' BEGIN {p=1} /^#start/ {print;system("cat exceptions");p=0} /^#end/ {p=1} p' acl.txt > newfile 

ENCORE UNE AUTRE VERSION SI VOUS VOULEZ VRAIMENT UTILISER SED

Si vous voulez vraiment le faire avec sed, vous pouvez utiliser des espaces d’adresse nesteds, tout d’abord pour sélectionner les lignes entre #start_exceptions et #end_exceptions, puis de nouveau pour sélectionner la première ligne et les lignes autres que la ligne #end_exceptions:

 sed ' /^#start/,/^#end/{ /^#start/{ n r exceptions } /^#end/!d } ' acl.txt 

Sortie:

 192.168.0.1 192.168.4.5 #start_exceptions 192.168.88.88 192.168.76.6 #end_exceptions 192.168.5.55 

RÉPONSE ORIGINALE

Je pense que cela fonctionnera:

 sed -e '/^#end/r exceptions' -e '/^#start/,/^#end/d' acl.txt 

Quand il trouve / ^ # end / il lit dans le fichier des exceptions. Et il supprime également tout entre / # start / et / # end /.

J’ai laissé la correspondance légèrement “relâchée” pour clarifier l’expression de la technique.

Vous pouvez utiliser les éléments suivants, basés sur Remplacer la chaîne par le contenu d’un fichier utilisant sed :

 $ sed $'/end/ {r exceptions\n} ; /start/,/end/ {d}' acl.txt 192.168.0.1 192.168.4.5 192.168.88.88 192.168.76.6 192.168.5.55 

Explication

  • sed $'one_thing; another_thing' ac1.txt sed $'one_thing; another_thing' ac1.txt effectue les deux actions.
  • /end/ {r exceptions\n} si la ligne contient end , lisez les exceptions du fichier et ajoutez-la.
  • /start/,/end/ {d} d’une ligne contenant le start d’une ligne contenant end , supprimez toutes les lignes.

J’ai eu des problèmes avec la solution de Mark Setchell dans MINGW. Le caret ne relevait pas le début de la ligne. En effet, la détection du séparateur dépend-elle de sa position au début de la ligne? Je suis venu avec cette alternative awk …

 $ awk -v data="$(