Utilisation de sed ou awk comment supprimer un motif autour d’une ligne de certian

Je dois supprimer un motif autour d’une certaine ligne:

#undef LZZ_INLINE #ifdef LZZ_ENABLE_INLINE #include "somename.inl" #endif 

Devraient devenir:

 #include "somename.inl" 

Je ne connais pas de somename à l’avance. Comment cela peut-il être fait en utilisant, par exemple, sed ou awk de manière générique?

Si la taille du fichier permet la lecture en le chargeant en une seule fois, vous pouvez le faire

 sed -i.bk ':a;$!{N;ba}; s/#undef LZZ_INLINE\n#ifdef LZZ_ENABLE_INLINE\n\(#include [^\n]*\)\n#endif/\1/g' input.file 

Supprimez le fichier .bk si tout se passe bien 🙂

pls essayer si cette oneliner fonctionnerait pour vous:

 awk '/#undef LZZ_INLINE/{next;} /#ifdef LZZ_ENABLE_INLINE/{x=1;next;}x&&/#endif/{x=0;next;}1' file 

ajoutez ceci à un fichier appelé fix.sed

 /^#undef LZZ_INLINE/{ N N N s/.*\(#include "[^"]*"\).*/\1/ } 

courez comme ceci:

sed -f fix.sed votre fichier d’origine

En supposant la réponse @glennjackman a posté:

 awk '/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} 1' file 

est correct et que vous souhaitez simplement mettre à jour le fichier d’entrée sur place, voici comment vous pouvez le faire avec awk:

 awk '/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} {out[++nr]=$0} END{close(FILENAME); for (i=1;i<=nr;i++) print out > FILENAME}' file 

(ie remplacer 1 par {out[++nr]=$0} END{close(FILENAME); for (i=1;i<=nr;i++) print out > FILENAME} )

Voici un autre:

 awk '/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} {print > "/tmp/\""FILENAME"\"" } END{system("mv /tmp/\""FILENAME"\" \""FILENAME"\""}' file 

(ie remplacer 1 par {print > "/tmp/\""FILENAME"\"" } END{system("mv /tmp/\""FILENAME"\" \""FILENAME"\""} )

Il y a quelques variations dans la manière de l’implémenter, mais l’idée de base est juste de mettre la sortie en mémoire tampon jusqu’à ce que vous ayez fini de lire le fichier d’entrée, puis d’écraser le fichier d’entrée. NBD dans les deux cas …

Une autre variante que je devrais mentionner est de créer un fichier tmp INPUT, qui ressemblerait à ceci:

 awk ' BEGIN{ tmp="/tmp/\"" ARGV[1] "\"" while ( (getline var < ARGV[1]) > 0 ) { print var > tmp } close(tmp) out = ARGV[1] ARGV[1] = tmp } /#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} {print > out}' file 

Que vous utilisiez un système (“mv …”) ou une boucle getline est du style ou dépend de ce que votre système d’exploitation fournit.