#1 Le 18/12/2020, à 14:52
- Brice Jeunieaux
[Résolu] Motif grep qui change au sein d'une boucle 'for'.
Bonjour / Bonsoir,
je cherche à afficher uniquement la première occurrence des lignes contenant mon motif qui contient lui-même une variable qui s'incrémente au sein d'une boucle for. Ça, c'est mon but final, clair et précis. Sachez qu'à force de chercher, chercher, chercher sur Internet, j'ai trouvé un moyen de faire, mais en ayant recours à des concepts que je ne comprends pas toujours, bien que le code final soit très simple, et c'est cela qui me dérange. Je souhaite trouver la solution la plus simple possible, si possible sans sortir du domaine de 'grep', 'sed', 'awk' et 'cut'.
Partie 1 : Voilà, j'ai actuellement ces lignes :
zone1;ligne1;
zone1;ligne2;
zone1;ligne3;
zone2;ligne1;
zone2;ligne2;
zone3;ligne1;
J'ai réussi à avoir ce que je voulais, c'est-à-dire, ceci :
zone1;ligne1;
zone2;ligne1;
zone3;ligne1;
Pour ce faire, non je n'ai pas fait un grep avec un motif "ligne1" parce que je voulais une solution qui fonctionne si la syntaxe des lignes dans mon fichier n'était pas respecté et ainsi donc que je me retrouvais sans certaines lignes. J'ai trouvé ça comme solution :
for i in $(grep "^zone" test2.txt | cut -d ";" -f1 | sort -u);
do
LC_ALL=C grep -m1 "$i" test2.txt;
done
Partie 2 : Le souci est que ce petit "LC_ALL=C", même en faisant des recherches sur Internet, est rempli de concepts que je ne saisis pas et je ne souhaite pas écrire un programme contenant du code que je ne maîtrise pas. Ainsi donc je recherche une alternative à cette solution, de préférence en utilisant uniquement au maximum grep, sed, cut et awk. Auriez-vous donc une idée de comment m'y prendre, en gardant mon code aussi propre et compréhensible que possible (méthode KISS) ?
Dernière modification par Brice Jeunieaux (Le 18/12/2020, à 20:27)
Hors ligne
#2 Le 18/12/2020, à 15:23
- Sciensous
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
1/ en cherchant avec "linux lc_all", je tombe sur lc_all
2/ ton script ne fait que regarder les termes zoneX et ne prend que le premier à chaque fois; pas sur que ce soit ce que tu veux
3/ je ne comprends pas ce que tu veux dire au début, concernant ton but
antiX 19 et 21 et Ubuntu 20.04 et 22.04
( sous LXDE et gnome-shell )
Hors ligne
#3 Le 18/12/2020, à 15:34
- Brice Jeunieaux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
1/ en cherchant avec "linux lc_all", je tombe sur lc_all
2/ ton script ne fait que regarder les termes zoneX et ne prend que le premier à chaque fois; pas sur que ce soit ce que tu veux
3/ je ne comprends pas ce que tu veux dire au début, concernant ton but
1/ Alors oui effectivement, j'ai déjà vu cette page mais le souci est que c'est rempli de concepts que je ne comprends ni ne maîtrise et quelque chose me dit qu'il doit tout de même bien exister une solution bien plus facile... Me connaissant, je sais pertinemment que si je code quelque chose que je ne maîtrise pas je vais m'embrouiller le cerveau.
2/ Alors justement, effectivement il fait ça, et c'est ce que je veux. Grosso modo, je fais du CSV avec une certaine mise en forme dans les données, et avec des grep etc je vais détecter si jamais il n'y a pas des lignes "corrompues" (mise en forme non respectée), des lignes à qui il manque un champ, etc... Du coup, dans mon programme, oui je souhaite regarder les termes 'zone1', 'zone2' etc, et ceci à des fins de divers traitements dont il n'est pas question ici mais oui c'est ce que je veux, juste trouver une manière plus compréhensible...
3/ En gros, la première phrase du topic (hors titre), c'est ce que je veux faire.
Ça ne rentrait juste pas dans le titre du topic donc j'ai préférer condenser le titre. Rien de plus.
Hors ligne
#4 Le 18/12/2020, à 15:46
- Sciensous
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
le lc_all=c permet de mettre la sortie dans le langage courant (français a priori)
le soucis que je voyais venait du sort -u qui ne prend que le premier, combiné au grep -m1 qui s'arrête aussi au premier.
Mais si tu dis que ça fait ce qu'il faut, ton script doit te convenir
Je suis pas assez programmateur pour bien analyser et/ou te proposer mieux
antiX 19 et 21 et Ubuntu 20.04 et 22.04
( sous LXDE et gnome-shell )
Hors ligne
#5 Le 18/12/2020, à 15:52
- Watael
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
LC_ALL=C indique d'utiliser la langue système par défaut : l'anglais.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#6 Le 18/12/2020, à 15:59
- pingouinux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
Bonjour,
Ceci ?
$ sort -t";" -u -k1,1 test2.txt
zone1;ligne1;
zone2;ligne1;
zone3;ligne1;
Hors ligne
#7 Le 18/12/2020, à 16:11
- Brice Jeunieaux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
le lc_all=c permet de mettre la sortie dans le langage courant (français a priori)
le soucis que je voyais venait du sort -u qui ne prend que le premier, combiné au grep -m1 qui s'arrête aussi au premier.
Mais si tu dis que ça fait ce qu'il faut, ton script doit te convenirJe suis pas assez programmateur pour bien analyser et/ou te proposer mieux
Alors, justement, pour le 'sort -u', c'est assez intéressant, parce qu'en le manipulant un peu, de ce que je vois (et j'ai bien lu la page man), il me permet de trier et de n'afficher que la première occurrence du champ affiché en sortie des lignes de données. Ce qu'il ne fait pas si je n'utilise pas la commande cut auparavant sur mon 'grep'. Allez, petite illustration pour que ce soit plus compréhensible.
Ça ce sont mes lignes de données brutes dans mon fichier :
zone1;infos;NomDeLaZone;catg-Int;
zone1;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone2;infos;Maison du héros;
zone2;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone3;infos;Entrée de la forêt;
zone3;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone4;infos;Lac;
zone4;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone5;infos;Village Maltebourges;
zone5;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
Ça c'est ce qu'il se passe quand je combine un 'grep' + 'cut' (rien de fou) :
grep "^zone" test2.txt | cut -d ";" -f1
zone1
zone1
zone2
zone2
zone3
zone3
zone4
zone4
zone5
zone5
Ça c'est ce qu'il se passe quand je combine le 'grep', le 'cut' et le 'sort -u' ensemble :
$ grep "^zone" test2.txt | cut -d ";" -f1 | sort -u
zone1
zone2
zone3
zone4
zone5
Enfin, et c'est là tout l'enjeu de ce que je viens de découvrir entre guillemets, ce qu'il se passe en combinant 'grep' et 'sort' sans le 'cut' :
$ grep "^zone" test2.txt | sort -u
zone1;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone1;infos;NomDeLaZone;catg-Int;
zone2;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone2;infos;Maison du héros;
zone3;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone3;infos;Entrée de la forêt;
zone4;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone4;infos;Lac;
zone5;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone5;infos;Village Maltebourges;
Tout ça pour dire par rapport au 'sort' qu'il n'a pas l'air de pouvoir trier correctement quand on ne filtre pas les champs à afficher avec 'cut'.
Et donc pour revenir au topic, ce que je remarque c'est que je n'ai à priori nullement besoin de la ligne faisant appel au lc_all=c, si je ne me trompe pas.
Hors ligne
#8 Le 18/12/2020, à 16:16
- Brice Jeunieaux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
Bonjour,
Ceci ?$ sort -t";" -u -k1,1 test2.txt zone1;ligne1; zone2;ligne1; zone3;ligne1;
Alors là, ça me laisse sur les fesses !
Je regarde la page man avec attention, et trifouilles la commande sort, notamment l'option 't' et 'k', et j'ai du mal à voir ce que ces options font, surtout 'k'. Peux-tu m'éclairer ? En tout cas, merci beaucoup, ça me facilite beaucoup la tâche. Ne reste plus qu'à voir à quoi sert l'option 'k' pour savoir si ça va m'être assez ou très utile.
Hors ligne
#9 Le 18/12/2020, à 16:28
- pingouinux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
-k n1,n2 : Le tri commence au champ n1 et s'arrête au champ n2
Hors ligne
#10 Le 18/12/2020, à 16:58
- Brice Jeunieaux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
-k n1,n2 : Le tri commence au champ n1 et s'arrête au champ n2
Mmmh... En jouant avec ces deux nombres, cela me donne des résultats qui rendent la chose difficile à comprendre.
Mon fichier actuel :
$ cat test2.txt
>zone0;infos;idZone;libZone;catgZone;
>zone0;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zone1;infos;NomDeLaZone;catg-Int;
zone1;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zoneX;infos;Jardin;catg-Ext;
zoneX;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zoneX;infos;Chambre1;catg-Int;
zoneX;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
zoneX;infos;Cuisine;catg-Int;
zoneX;directions;n0-s0-e0-w0-ne0-nw0-se0-sw0-u0-d0;
Ce qu'il m'affiche en tapant cette commande :
$ sort -t ";" -u -k1,1 test2.txt
>zone0;infos;idZone;libZone;catgZone;
zone1;infos;NomDeLaZone;catg-Int;
zoneX;infos;Jardin;catg-Ext;
Les lignes de données avec les chevrons fermants, c'est normal que ce soit là mais ce n'est pas à considérer comme des lignes de données exploitables, c'est juste un modèle en guise de commentaire pour que n'importe qui puisse comprendre la mise en forme. Du coup ce n'est pas à traiter et la commande le fait, malheureusement. Du coup est-ce que c'est possible d'avoir le pourquoi du comment ces valeurs de paramètres de commande me donnent ça en sortie ?
Hors ligne
#11 Le 18/12/2020, à 17:24
- pingouinux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
$ sort -t";" -u -k 1,1 test2.txt | grep -v '^>'
zone1;infos;NomDeLaZone;catg-Int;
zoneX;infos;Jardin;catg-Ext;
Hors ligne
#12 Le 18/12/2020, à 17:42
- Sciensous
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
quand je disais que je n'étais pas assez programmateur pingouinux est d'un autre calibre
(Watel aussi)
ce que je peux te dire: le grep cherche un motif mais affichera toute la ligne contenant ce motif (à moins de mettre l'option -o)
c'est pour ça que tu as imbriqué plusieurs commandes; qui peuvent se simplifier par une seule - c'est toute la force du shell !
mais faut maitriser les subtilités de ce langage puissant
le lc_all devait servir à mettre les majuscules avant les minuscules, c'est juste un avis
Dernière modification par Sciensous (Le 18/12/2020, à 17:43)
antiX 19 et 21 et Ubuntu 20.04 et 22.04
( sous LXDE et gnome-shell )
Hors ligne
#13 Le 18/12/2020, à 18:16
- pingouinux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
le lc_all devait servir à mettre les majuscules avant les minuscules, c'est juste un avis
C'est exact. On peut aussi faire
LC_COLLATE=C sort ...
Hors ligne
#14 Le 18/12/2020, à 20:27
- Brice Jeunieaux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
Bon, du coup, tout ce que je veux faire fonctionne et sans avoir de code complexe.
Je n'ai finalement ni eu besoin d'avoir recours au lc_all ou encore à la longue commande sort de pingouinux (merci quand même, j'ai quand même appris de cette commande).
En effet, la solution que j'ai retenu est la concaténation de commandes :
grep "^zone" test2.txt | cut -d ";" -f 1 | sort -u
Tout simplement. Elle me permet de n'avoir qu'une seule occurrence de chaque ligne filtrée, grâce à sort.
Encore merci d'avoir jeté un œil et offert des solutions, je passe le sujet en résolu mais si quelqu'un a des questions par rapport à ma solution retenue, je reste à disposition.
Hors ligne
#15 Le 19/12/2020, à 02:34
- kamaris
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
Si j'ai bien suivi le tri n'est pas nécessaire ?
Est-ce que ça ce ne serait pas suffisant :
awk -F';' '/^zone/ && !a[$1]++' test2.txt
Hors ligne
#16 Le 19/12/2020, à 09:43
- pingouinux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
@kamaris #15 :
Le sort -u ne servait qu'à éliminer les doublons. Ta méthode a l'avantage de tout faire en une seule commande et de conserver les zones dans l'ordre.
Hors ligne
#17 Le 24/12/2020, à 20:07
- Brice Jeunieaux
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
@kamaris #15 :
Le sort -u ne servait qu'à éliminer les doublons. Ta méthode a l'avantage de tout faire en une seule commande et de conserver les zones dans l'ordre.
Exactement. Je vais tester la méthode de Kamaris voir si elle me convient (désolé, je n'ai pu répondre plus tôt).
Edit : alors j'ai testé la solution de Kamaris et clairement, il faut vraiment que je me mette à apprendre 'awk' parce que cette commande, c'est parfait. J'ai des lignes commençant par "zone164" ou encore "zone645984849" et cette commande me retourne les lignes dans l'ordre qu'elles sont écrites dans le fichier, c'est parfait. Je vais voir pour trier ensuite l'affichage sur la sortie par ordre alphabétique du troisième champ. Je suis sûr que je peux faire ça avec 'awk'. Encore merci !
Dernière modification par Brice Jeunieaux (Le 24/12/2020, à 20:15)
Hors ligne
#18 Le 25/12/2020, à 12:48
- kamaris
Re : [Résolu] Motif grep qui change au sein d'une boucle 'for'.
Avec awk pas sûr, avec gawk surement, mais pour le coup, il vaudrait peut-être mieux passer tranquillement la sortie de awk à sort, qui est fait pour ça.
Hors ligne