#1 Le 11/04/2021, à 14: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é
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 ) 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, à 15:41)
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#2 Le 11/04/2021, à 15: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, à 15:17)
Hors ligne
#3 Le 11/04/2021, à 15:19
- nany
Re : [Résolu] Supprimer blocs de texte entre 2 motifs.
Bonjour,
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
En ligne
#4 Le 11/04/2021, à 15:37
- Tawal
Re : [Résolu] Supprimer blocs de texte entre 2 motifs.
Whaou !
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é
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#5 Le 11/04/2021, à 15:38
- Beta Pictoris
Re : [Résolu] Supprimer blocs de texte entre 2 motifs.
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 ?
Dernière modification par Beta Pictoris (Le 11/04/2021, à 15:39)
Hors ligne
#6 Le 11/04/2021, à 15:56
- nany
Re : [Résolu] Supprimer blocs de texte entre 2 motifs.
Oui, c’est largement mieux.
J’ai codé un peu à l’arrache en me rendant compte que c’était largement améliorable.
En ligne
#7 Le 11/04/2021, à 16: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.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#8 Le 11/04/2021, à 17: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é
Merci.
Dernière modification par Tawal (Le 11/04/2021, à 17:34)
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#9 Le 11/04/2021, à 17: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, à 17:40)
Hors ligne
#10 Le 12/04/2021, à 00: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, à 06: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, à 06:21)
En ligne
#12 Le 12/04/2021, à 10:08
- Tawal
Re : [Résolu] Supprimer blocs de texte entre 2 motifs.
Super, vous êtes des zamours du code
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
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#13 Le 12/04/2021, à 12: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
Edit ps :
Les 2 versions awk et sed sont inscrites dans mon script pour mémoire
Edit2:
Désolé pour perl mais j'y pip que dalle aussi
Dernière modification par Tawal (Le 12/04/2021, à 12:31)
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne
#14 Le 15/04/2021, à 21:06
- Beta Pictoris
Re : [Résolu] Supprimer blocs de texte entre 2 motifs.
Edit2:
Désolé pour perl mais j'y pip que dalle aussi
Ça t’empêche pas de faire un benchmark en perl aussi ? Hein ?
Hors ligne
#15 Le 15/04/2021, à 21: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é
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
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, à 07:59)
Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !
Hors ligne