J’utilise grep pour filtrer selon un motif et re-diriger le résultat vers un fichier.
Je voudrais qu’un deuxième fichier soit généré, contenant lui les lignes ne correspondant pas au motif, le fichier complémentaire en quelque sorte.
Je peux m’en sortir en appelant deux fois grep, ou en utilisant diff, ou d’autres méthodes j’imagine, mais je voudrais savoir s’il y a une méthode plus élégante/concise/efficiente de faire cela. Je vais être honnête : je cherche LA bonne manière de faire pour briller en société. Ne me décevez pas ! ;)
Je ne suis pas bloqué sur grep, j’ai regardé ces exemples avec awk mais je n’ai pas trouvé de réponse qui me convienne, j’ai peut-être lu trop vite cela dit.
# stderr
Posté par gaaaaaAab . Évalué à 3.
Si le challenge, c'est de le faire en une seule commande, awk sait écrire sur stderr. En répartissant tes lignes sur stderr et stdout, et en mettant les bonnes redirections, ça doit le faire.
Par contre, c'est franchement de la bidouille, je ne pense pas que ça passe le test de l'élégance :-)
A part ça, avec juste les commandes classiques du shell, pour l'instant, je ne vois pas comment utiliser moins que deux commandes …
[^] # Re: stderr
Posté par wismerhill . Évalué à 5.
Pas besoin de jouer avec stderr, awk peut écrire dans des fichiers quelconques, par exemple avec la syntaxe
[^] # Re: stderr
Posté par gaaaaaAab . Évalué à 3.
tout à fait, ça marche très bien … quand on n'essaie pas d'abuser de stderr pour avoir deux flux en sortie au lieu d'un seul :-)
[^] # Re: stderr
Posté par gaaaaaAab . Évalué à 3.
ah oui, je vois ce que tu veux dire. Effectivement, c'est pas bien malin d'utiliser stderr comme un gros sale alors qu'on faire propre directement.
[^] # Re: stderr
Posté par Michaël (site web personnel) . Évalué à 5.
En fait awk sait même écrire dans des fichiers, par exemple voici comment obtenir la sortie dans deux fichiers
output.a
etoutput.b
:Au passage l'extrait illustre le passage de paramètres à awk ce qu'on peut utiliser pour choisir les noms de fichiers depuis la procédure appelante.
(Cela marche avec awk sans tirer parti d'aucune extension, ce que je souligne pour la portabilité!)
[^] # Re: stderr
Posté par gaaaaaAab . Évalué à 2.
oui, c'est en substance ce que dit wismerhill dans son commentaire, mais de façon plus lapidaire. D'ailleurs, je ne l'avais pas compris tout de suite non plus. Tu fais bien d'expliciter. Si tu ne l'as pas interprété comme ça alors que tu le savais, d'autres lecteurs peuvent aussi être passé à côté.
# sed
Posté par Cyril Brulebois (site web personnel) . Évalué à 5.
Ce n'est probablement pas la première chose qu'on aperçoit avec cet outil, mais
sed
propose :Ça peut être une bonne idée de faire un tour de la liste des commandes disponibles dans GNU sed ; par ailleurs,
w
est spécifié dans POSIX.Exemple de cours classique : partir de la sortie de
seq
et générer un fichierpairs
et un fichierimpairs
.Enjoy.
Debian Consultant @ DEBAMAX
[^] # Re: sed
Posté par gaaaaaAab . Évalué à 2.
sed sait fait trop de trucs :-)
Tiens, question, qui vaut tant pour awk que pour sed, est-ce que quelqu'un sait si ces outils gardent les fichiers ouverts pendant tout le traitement en gérant une table des fichiers rencontrés dans le script ? ou est-ce que chaque fichier est réouvert et refermé à chaque opération d'écriture ? (Si personne ne sait, je ferais quelques tests, mais là je n'ai pas le temps).
[^] # Re: sed
Posté par Cyril Brulebois (site web personnel) . Évalué à 1.
J'aurais imaginé une seule ouverture du fichier au tout début (ou des fichiers si plusieurs expressions avec
-e
sont spécifiées), et c'est ce que semble confirmer un petitstrace
.Debian Consultant @ DEBAMAX
# grep -v
Posté par eggus . Évalué à -1.
A moins que je n'ai pas du tout compris l'objectif, juste :
grep -v motif fichier_source > fichier_sortie
[^] # Re: grep -v
Posté par eggus . Évalué à 4.
j'ai pris un café et maintenant en effet je vois que j'ai mal compris le problème :)
# awk
Posté par Pouetpouet . Évalué à 3.
awk (en tout cas la version gawk que j'ai sous la main) peut écrire dans des fichiers différents en fonction de tes conditions
[^] # Re: awk
Posté par wismerhill . Évalué à 4.
Avec $1 tu va seulement écrire (et tester, dans ton if) le premier champ de la ligne, pour la ligne complète il faut utiliser $0 (ou même print sans paramètres).
[^] # Re: awk
Posté par Marotte ⛧ . Évalué à 3.
Je pense que c’est ce que je vais faire (il faut aussi que je regarde sed, comme a suggéré Cyril).
J’avais pensé à un truc de ce genre mais en utilisant deux motifs distincts, j’avais pas pensé à utiliser "else"…
Encore un grand merci à tous. Vous assurez.
# comm
Posté par gUI (Mastodon) . Évalué à 1.
Alors j'ai pas plus testé que ça, mais je crois bien que comm fait ça.
C'est sympa de voir le nb de solutions différentes au même pb :)
En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.
[^] # Re: comm
Posté par gUI (Mastodon) . Évalué à 2. Dernière modification le 21 décembre 2017 à 08:43.
Après vérification, c'est exactement ce pour quoi
comm
est fait. Il te sort directement ce qui est commun, ce qui n'est que dans le premier fichier et ce qui n'est que dans la 2nd. A la fois diff et grep en quelques sortes.Par contre il a un pré-requis peut-être rédhibitoire : les lignes doivent être triées.
En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.
[^] # Re: comm
Posté par Marotte ⛧ . Évalué à 3.
Merci pour ton commentaire je connaissais pas cette commande donc +1 pour ça.
Ça doit être possible de s’en sortir avec diff aussi. C’est un peu con que tu te fasses moinsser parce que tu n’as pas pris le soin de préciser que ça ne répondait pas à ma demande (j’avais bien spécifié de si possible avoir à appeler un seul binaire)… Mais bon, tu connais le site il me semble :)
J’ai pas encore eu le temps de me remettre à travailler sur le script en question mais j’essaierai de faire un retour sur la solution choisie.
[^] # Re: comm
Posté par gUI (Mastodon) . Évalué à 1.
Surtout que
comm
te fait 3 colonnes (seulement dans fichier1, seulement dans fichier2, commun). Ensuite pour filtrer et en sortir des fichiers distinct… va falloir sortir awk :)En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.
# Pas très élégant mais fonctionnel
Posté par guppy . Évalué à 4.
[^] # Re: Pas très élégant mais fonctionnel
Posté par freem . Évalué à 3.
je n'avais pas propose tee parce que je pensais que l'objectif etait de ne parser qu'une seule fois… sinon y'a aussi moyen avec socat je pense, mais on rdntre dans l'esoterisme bourne apres :)
[^] # Re: Pas très élégant mais fonctionnel
Posté par Marotte ⛧ . Évalué à 3.
Le problème de cette approche, or le fait, comme le dit freem, de devoir parser le fichier deux fois (à la rigueur s’il n’y a pas trop de lignes ça peut aller), c’est surtout au niveau des expressions régulières que je sens venir le piège… Il faut que je détermine ma regex ainsi que sa complémentaire. Là je dois pouvoir encore le faire sans me gourrer, mais si la regex doit être rendue plus complexe, je vais pouvoir me retrouver avec des lignes dans les deux fichiers ou des lignes nulle part…
Je commence à m’en vouloir un peu de ne pas avoir pensé moi-même au bête mot-clé else… J’ai probablement pas une assez bonne maîtrise de awk (ou sed) pour les considérer à juste titre comme des langages de programmation complets.
[^] # Re: Pas très élégant mais fonctionnel
Posté par Marotte ⛧ . Évalué à 3.
#_# Et là c’est moi qui raconte carrément n’importe quoi… si
grep -v regexA
renvoyait pas le complément degrep regexA
ce serait un sacré bug :)Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.