Contenu | Rechercher | Menus

Annonce

DVD, clés USB et t-shirts Ubuntu-fr disponibles sur la boutique En Vente Libre

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 11/04/2021, à 15:34

Tawal

[Résolu] Supprimer blocs de texte entre 2 motifs.

Hello,

Je sais déjà que mon titre n'est pas assez explicatif.
Pour cela je vais donner un exemple (générique) de fichier que je veux traiter et expliquer quel traitement je souhaiterais.

Fichier type :

Motif_1...Motif_2...
   lignes.....
   ....
Motif_1......
   lignes...
   .....
Motif_1...Motif_2
   lignes ...
   ....
Motif_1...
   lignes ...

J'ai indenté pour la lisibilité wink

Ce que je voudrais faire, c'est supprimer les lignes Motif_1..Motif_2 jusqu'à la ligne Motif_1 suivante.
Et garder tous les blocs Motif_1....  (sans Motif_2 évidemment big_smile) avec leurs lignes correspondantes.
Le nombre de lignes dans les blocs est variable.
Il n' y a pas de motif_3 pour signaler la fin d'un bloc.

En gros, ça revient à supprimer les paragraphes (non séparés par des lignes vides) Motif_1...Motif_2.
En prenant Motif_1 comme repère de paragraphe.

Je ne voudrais pas proposer un problème XY, mais je me doute qu'un sed bien construit ferait l'affaire ...

En vous remerciant de vos aides, éclairages, pistes ou autres ...

Dernière modification par Tawal (Le 11/04/2021, à 16:41)


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne

#2 Le 11/04/2021, à 16:05

Beta Pictoris

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

cat list.txt
Motif_1...Motif_2...
   lignes.....
   ....
Motif_1...
   lignes...
   .....
Motif_1...Motif_2...
   lignes ...
   ....
Motif_1...
   lignes ...
perl -n -e '$f+=1 if /^Motif_1.*Motif_2/;$f-=1 if /^Motif_1/ and !/Motif_2/; print unless $f' list.txt
Motif_1
   lignes...
   .....
Motif_1
   lignes ...

Dernière modification par Beta Pictoris (Le 11/04/2021, à 16:17)

Hors ligne

#3 Le 11/04/2021, à 16:19

nany

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Bonjour,


Tawal a écrit :

Je ne voudrais pas proposer un problème XY, mais je me doute qu'un sed bien construit ferait l'affaire ...

Avec sed je ne sais pas (c’est sûrement possible) mais j’ai préféré awk :

awk 'BEGIN {s=0} /Motif_2/{s=1 ; next ; while (!/Motif_1/) next} ; /Motif_1/ && !/Motif_2/{s=0} ; {if (s==0) { print } }' fichier

Hors ligne

#4 Le 11/04/2021, à 16:37

Tawal

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Whaou ! smile

Merci de vos réponses rapides.

Les 2 solutions fonctionnent très bien perl et awk.
Je retiendrais plus aisément la solution awk car je connais déjà un peu sa syntaxe tandis que je ne touche pas du tout à perl.

Je pensais de primo à sed pour son édition "in place".
Bon, je vais devoir étudier cette commande awk pour maîtriser ce qui s'y passe vraiment.

Merci à vous deux pour la rapidité mais aussi pour l'efficacité wink


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne

#5 Le 11/04/2021, à 16:38

Beta Pictoris

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

nany a écrit :

Bonjour,

awk 'BEGIN {s=0} /Motif_2/{s=1 ; next ; while (!/Motif_1/) next} ; /Motif_1/ && !/Motif_2/{s=0} ; {if (s==0) { print } }' fichier

Ok, mais ton code awk peut-être simplifié :

awk 'BEGIN {s=0} /Motif_2/{s=1} /Motif_1/ && !/Motif_2/{s=0} s==0 {print }' fichier

C'est pas mieux ansi ? smile

Dernière modification par Beta Pictoris (Le 11/04/2021, à 16:39)

Hors ligne

#6 Le 11/04/2021, à 16:56

nany

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Oui, c’est largement mieux. big_smile
J’ai codé un peu à l’arrache en me rendant compte que c’était largement améliorable. wink

Hors ligne

#7 Le 11/04/2021, à 17:23

Tawal

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Surprenant !

Je comprends (avec réflexion) vos commandes (pas perl), ça paraît simple quand c'est écrit mais à composer ...
Bravo !

Merci.


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne

#8 Le 11/04/2021, à 18:33

Tawal

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Re,

Une autre question :
Comment intégrer une variable à la place des Motifs ?

J'ai trouvé wink

Merci.

Dernière modification par Tawal (Le 11/04/2021, à 18:34)


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne

#9 Le 11/04/2021, à 18:39

Beta Pictoris

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Pour information, j'ai utilisé la méme méthode que nany. D'ailleurs, je peux faire ressembler le script perl au script awk :

perl -n -e 'BEGIN { $s=0 }; if ( /Motif_2/ ) { $s=1 }; if (/Motif_1/ && !/Motif_2/) { $s=0 }; if ( $s==0 ) { print }' fichier

Dernière modification par Beta Pictoris (Le 11/04/2021, à 18:40)

Hors ligne

#10 Le 12/04/2021, à 01:50

kamaris

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Une possibilité avec sed :

sed '/^Motif_1.*Motif_2/,/^Motif_1/{/^Motif_1/!d; /Motif_2/d}' fichier

Hors ligne

#11 Le 12/04/2021, à 07:17

nany

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Je savais bien que c’était possible avec sed.

Et c’est la solution la plus rapide, en tout cas sur cet exemple de fichier.

[edit]
encore plus rapide :

sed '/Motif_2/,/^Motif_1/{/^Motif_1/!d; /Motif_2/d}' fichier

[/edit]

Dernière modification par nany (Le 12/04/2021, à 07:21)

Hors ligne

#12 Le 12/04/2021, à 11:08

Tawal

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Super, vous êtes des zamours du code big_smile

Question rapidité, les 2 se valent (entre sed et awk).
Le code de sed est un peu plus concis.

Un résultat de performance sur un fichier d'environ 60 000 lignes :

$ time awk 'BEGIN {s=0} /'"$a"'/{s=1} /'"$b"'/ && !/'"$a"'/{s=0} s==0 {print }' fichier.test
...
real	0m1,111s
user	0m0,183s
sys	0m0,328s
$
$ time sed '/'"$a"'/,/^'"$b"'/{/^'"$b"'/!d; /'"$a"'/d}' fichier.test
...
real	0m0,936s
user	0m0,089s
sys	0m0,266s
$

awk ne descend jamais en dessous de la seconde.
sed rarement.
En moyenne, ils sont à peu près égaux (sur plusieurs tests).
sed possède une petite avance qui se ferait sentir sur de très gros fichier.

Encore merci à vous.
Et finalement, je vais adopter la solution sed, car plus rapide (un chouia) et plus concise smile


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne

#13 Le 12/04/2021, à 13:24

Tawal

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Re,

J'ai dû adapter selon mes besoins :
En effet, en travaillant sur de petits motifs, le Motif_2 peut se retrouver dans les lignes de blocs.
Pour éviter les mauvaises découpes, j'ai fait comme ceci :
Motifs en dur :

sed '/^Motif_1.*Motif_2/,/^Motif_1/{/^Motif_1/!d; /Motif_2/d}' fichier

Motifs en variable :

sed '/^'"$Mot_1"'.*'"$Mot_2"'/,/^'"$Mot_1"'/{/^'"$Mot_1"'/!d; /'"$Mot_2"'/d}' fichier

À savoir que Mot_1 est une chaîne invariante.
Et que Mot_2 peut ne pas être une simple chaîne d'où l'expression "motif".

Merci à vous smile

Edit ps :
Les 2 versions awk et sed sont inscrites dans mon script pour mémoire wink

Edit2:
Désolé pour perl mais j'y pip que dalle aussi lol

Dernière modification par Tawal (Le 12/04/2021, à 13:31)


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne

#14 Le 15/04/2021, à 22:06

Beta Pictoris

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

Tawal a écrit :

Edit2:
Désolé pour perl mais j'y pip que dalle aussi lol

Ça t’empêche pas de faire un benchmark en perl aussi ? Hein ? wink

Hors ligne

#15 Le 15/04/2021, à 22:34

Tawal

Re : [Résolu] Supprimer blocs de texte entre 2 motifs.

J'aurais bien voulu, mais ta commande ne fonctionne pas sur mes fichiers.
Elle fonctionne très bien sur le fichier exemple du #1.

Sur mes fichiers, ça me supprime tous les blocs, peut-être parce que dans les lignes du fichier, il y a pas mal de caractères "spéciaux" : = / % etc ...
De plus, perl serait sensible aux caractères latins (çàéè ...), j'ai essayé de lui en passer en motif, il n'a pas apprécié big_smile
Après, comme je ne connais rien à perl, je ne peux pas déboger.

Donc, désolé pour le test de performance.
En tout cas, il est rapide à me vider les 60 000 lignes lol

Edit:
Pour les caractères latins dans le Motif_2, je crois que perl les traduits en caractères hexadécimaux et recherche sur chaque caractère hexadécimal.
Donc comme, par exemple, le "ç s'écrit sur 2 caractères hexa \xC3 et \xA7 et que le caractère \xC3 n'est pas un caractère affichable, perl renvoie une erreur.

Dernière modification par Tawal (Le 16/04/2021, à 08:59)


Le savoir n'a d’intérêt que si on le transmet.
Ubuntu-Mate 20.04.2 LTS Virtualisée
Useless Use of Cat Award

Hors ligne