A voir également:
- Parcours de fichiers avec sed
- Wetransfer gratuit fichiers lourd - Guide
- Explorateur de fichiers - Guide
- Renommer plusieurs fichiers - Guide
- Fichiers bin - Guide
- Impossible de supprimer un fichier - Guide
17 réponses
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
9 déc. 2009 à 16:16
9 déc. 2009 à 16:16
Salut,
parcourir une liste de fichiers, et pour chacun regarder le 8ième champ délimité par des ';'.
Il n'y a qu'une ligne dans tes fichiers ?
Ou c'est à chaque ligne qu'il faut tester ?
Sur ce champ-là, je vérifie que c'est une date correcte,
Qu'appelles-tu une "date correcte" ?
Merci de poster un exemple concret de ton fichier et de ce que tu veux faire exactement...
Je ne pense pas que "sed" soit l'outil adéquat ;-\
parcourir une liste de fichiers, et pour chacun regarder le 8ième champ délimité par des ';'.
Il n'y a qu'une ligne dans tes fichiers ?
Ou c'est à chaque ligne qu'il faut tester ?
Sur ce champ-là, je vérifie que c'est une date correcte,
Qu'appelles-tu une "date correcte" ?
Merci de poster un exemple concret de ton fichier et de ce que tu veux faire exactement...
Je ne pense pas que "sed" soit l'outil adéquat ;-\
Oui désolé je suis tellement dans mon problème que j'ai du mal à être clair...
Donc mes fichiers ont plusieurs (milliers) de lignes, et sont sous cette forme :
un;deux;trois;quatre;cinq;six;sept;15/08/2006;neuf;dix
un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix
un;deux;trois;quatre;cinq;six;sept;;neuf;dix
un;deux;trois;quatre;cinq;six;sept;01/01/2010;neuf;dix
Donc avec cet exemple, les lignes 2 et 3 sont mal formatées, les lignes 1 et 4 oui. Une date correcte pour moi est (comme l'indique l'expression régulière) : un nombre de 00 à 39, suivi de / suivi d'un nombre de 00 à 19 suivi de / suivi d'un nombre de 0000 à 9999. C'est un peu permissif pour un controle de date, mais ça me suffit.
Au sujet de sed, je me suis dit que c'était une fonction bien optimisée et donc rapide, et elle me permettrait de réaliser mon traitement plus rapidement qu'avec mon premier script.
Merci !
Donc mes fichiers ont plusieurs (milliers) de lignes, et sont sous cette forme :
un;deux;trois;quatre;cinq;six;sept;15/08/2006;neuf;dix
un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix
un;deux;trois;quatre;cinq;six;sept;;neuf;dix
un;deux;trois;quatre;cinq;six;sept;01/01/2010;neuf;dix
Donc avec cet exemple, les lignes 2 et 3 sont mal formatées, les lignes 1 et 4 oui. Une date correcte pour moi est (comme l'indique l'expression régulière) : un nombre de 00 à 39, suivi de / suivi d'un nombre de 00 à 19 suivi de / suivi d'un nombre de 0000 à 9999. C'est un peu permissif pour un controle de date, mais ça me suffit.
Au sujet de sed, je me suis dit que c'était une fonction bien optimisée et donc rapide, et elle me permettrait de réaliser mon traitement plus rapidement qu'avec mon premier script.
Merci !
bob031
Messages postés
8158
Date d'inscription
samedi 7 août 2004
Statut
Membre
Dernière intervention
1 septembre 2014
472
9 déc. 2009 à 16:35
9 déc. 2009 à 16:35
Bonjour,
qui dit "champ" .... dit awk !
:-)
qui dit "champ" .... dit awk !
:-)
et awk est rapide ? As-tu sous la main un exemple d'utilisation avec parcours de champ ? Juste pour m'aider à démarrer car je ne connais vraiment pas...
Merci !
Merci !
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
bob031
Messages postés
8158
Date d'inscription
samedi 7 août 2004
Statut
Membre
Dernière intervention
1 septembre 2014
472
9 déc. 2009 à 16:45
9 déc. 2009 à 16:45
pas mes cours awk sous le coude pour l'instant !
regarderai ce soir !
en attendant si cela peut t'aider (il y a des exemples) :
https://www.funix.org/fr/unix/awk.htm
http://www.shellunix.com/awk.html
regarderai ce soir !
en attendant si cela peut t'aider (il y a des exemples) :
https://www.funix.org/fr/unix/awk.htm
http://www.shellunix.com/awk.html
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
9 déc. 2009 à 17:35
9 déc. 2009 à 17:35
Essaye ça :
;-))
[tmpfs]$ cat data un;deux;trois;quatre;cinq;six;sept;15/08/2006;neuf;dix un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix un;deux;trois;quatre;cinq;six;sept;;neuf;dix un;deux;trois;quatre;cinq;six;sept;01/01/2010;neuf;dix un;deux;trois;quatre;cinq;six;sept;31/10/2009;neuf;dix un;deux;trois;quatre;cinq;six;sept;32/11/2008;neuf;dix un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix [tmpfs]$ awk -F";" '$8 !~ /([0-2][0-9]|30|31)+\/0[1-9]|1[0-2]\/[0-9]{4}/ { print "Ligne : "NR" pas OK" }' data Ligne : 2 pas OK Ligne : 3 pas OK Ligne : 5 pas OK Ligne : 6 pas OK Ligne : 7 pas OK [tmpfs]$
;-))
Merci !
c'est cela qu'il me fallait effectivement. Par contre lorsque je l'ai imbriqué dans ma boucle for qui parcoure les répertoires pour trouver les fichiers, alors l'expression régulière ne reconnait plus rien, toutes les lignes sont fausses...
Par contre, je vois un souci aussi dans ton exemple : la ligne 5 devrait être bonne, le 31/10/2009 est une bonne date.
c'est cela qu'il me fallait effectivement. Par contre lorsque je l'ai imbriqué dans ma boucle for qui parcoure les répertoires pour trouver les fichiers, alors l'expression régulière ne reconnait plus rien, toutes les lignes sont fausses...
Par contre, je vois un souci aussi dans ton exemple : la ligne 5 devrait être bonne, le 31/10/2009 est une bonne date.
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
10 déc. 2009 à 11:43
10 déc. 2009 à 11:43
Effectivement il y a un problème dans la regex ;-((
Pas trop le temps là de voir d'où ça vient, désolé ;-(
Pas trop le temps là de voir d'où ça vient, désolé ;-(
Bon j'ai bien avancé, et je vais m'arrêter là pour l'instant, je ne suis pas payé pour passer mes journées là dessus (malheureusement). La commande suivante fonctionne :
awk -F";" '$8 !~ /([0-3][0-9])\/([0-1][0-9])\/([0-2][0-9][0-9][0-9])/ { print "Fichier "FILENAME" Ligne : "NR" date mauvaise : "$8}' ${fichier} >> ${log}
En fait, le | n'est pas accepté par awk pour faire un ou, ni les { } pour utiliser le multiplicateur.Est-ce une limitation de gawk ? Je ne sais pas, je laisse le topic ouvert si jipicy ou quelqu'un d'autre veut mettre une solution plsu élégante.
Et merci à ceux qui m'ont répondu !
awk -F";" '$8 !~ /([0-3][0-9])\/([0-1][0-9])\/([0-2][0-9][0-9][0-9])/ { print "Fichier "FILENAME" Ligne : "NR" date mauvaise : "$8}' ${fichier} >> ${log}
En fait, le | n'est pas accepté par awk pour faire un ou, ni les { } pour utiliser le multiplicateur.Est-ce une limitation de gawk ? Je ne sais pas, je laisse le topic ouvert si jipicy ou quelqu'un d'autre veut mettre une solution plsu élégante.
Et merci à ceux qui m'ont répondu !
Salut,
Je ne sais pas mais c'est peut être le quantificateur {4} qui pose de problèmes
Voici un exemple sans {4}
Ligne : 2 pas OK 5/08/2006
Ligne : 3 pas OK
Ligne : 7 pas OK 25/1/2009
En revanche si un seul champ contient la date, un simple egrep te suffit, pas besoin de awk.
Le lignes sont affiché avec le numéro devant.
Je ne sais pas mais c'est peut être le quantificateur {4} qui pose de problèmes
Voici un exemple sans {4}
awk -F";" '$8 !~ /([0-2][0-9]|3[01])\/0[1-9]|1[0-2]\/[0-9][0-9][0-9][0-9]/ { print "Ligne : "NR" pas OK " $8}' data
Ligne : 2 pas OK 5/08/2006
Ligne : 3 pas OK
Ligne : 7 pas OK 25/1/2009
En revanche si un seul champ contient la date, un simple egrep te suffit, pas besoin de awk.
Le lignes sont affiché avec le numéro devant.
egrep -vn '([0-2][0-9]|3[01])+\/0[1-9]|1[0-2]\/[0-9]{4}' data 2:un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix 3:un;deux;trois;quatre;cinq;six;sept;;neuf;dix 7:un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix
Non il y a toujours un souci : le 32/11/2009 fonctionne, c'est à dire qu'il n'est pas repéré comme date mauvaise (je ne sais pas pourquoi, à mon avis il s'embrouille au niveau des priorités des opérateurs).
Par contre bonne idée pour le egrep, mais effectivement j'ai plusieurs dates par lignes.
Sinon une autre solution, d'un collègue qui "pense autrement" :
awk 'BEGIN { print "Debut du traitement";
FS=";"}
substr($8,1,2)>31 ||substr($8,4,2)>12 ||substr($8,7,4) !~ /([0-9][0-9][0-9][0-9])/ || substr($8,3,1)!= "/" { print "Ligne : "$8" "NR" pas OK " }
END {print "fin traitement"}
' test.txt
Merci !
Par contre bonne idée pour le egrep, mais effectivement j'ai plusieurs dates par lignes.
Sinon une autre solution, d'un collègue qui "pense autrement" :
awk 'BEGIN { print "Debut du traitement";
FS=";"}
substr($8,1,2)>31 ||substr($8,4,2)>12 ||substr($8,7,4) !~ /([0-9][0-9][0-9][0-9])/ || substr($8,3,1)!= "/" { print "Ligne : "$8" "NR" pas OK " }
END {print "fin traitement"}
' test.txt
Merci !
Salut,
Pour la regex il fallait mettre le motif pour les dates entre parenthèses. 0[1-9]|1[0-2]
Pourquoi?
Sans les parenthèses on lira comme ça
0[1-9]|1[0-2]
- cherche un 0 suivi soit d'un chiffre de 1 à 9 soit du chiffre 1 suivi d'un chiffre entre 0 et 2
Ce n'est pas ça qu'on veut.
Si on mets le parenthèses (0[1-9]|1[0-2]) alors on lira
- cherche un 0 suivi d'un chiffre de 1 à 9 ou cherche 1 suivi d'un chiffre de 0 à 2
Avec awk
Pour grep je saute les 1ers 7 champs et je teste sur le 8ème.
Avec grep
Pour la regex il fallait mettre le motif pour les dates entre parenthèses. 0[1-9]|1[0-2]
Pourquoi?
Sans les parenthèses on lira comme ça
0[1-9]|1[0-2]
- cherche un 0 suivi soit d'un chiffre de 1 à 9 soit du chiffre 1 suivi d'un chiffre entre 0 et 2
Ce n'est pas ça qu'on veut.
Si on mets le parenthèses (0[1-9]|1[0-2]) alors on lira
- cherche un 0 suivi d'un chiffre de 1 à 9 ou cherche 1 suivi d'un chiffre de 0 à 2
Avec awk
$ cat data un;01/1/2010deux;trois;quatre;cinq;six;sept;15/08/2006;neuf;dix un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix un;deux;2/5/2009;quatre;cinq;six;sept;;neuf;dix un;deux;trois;quatre;cinq;six;sept;01/01/2010;neuf;dix un;deux;trois;quatre;7/10/2010;six;sept;31/10/2009;neuf;dix un;deux;trois;quatre;cinq;six;sept;32/11/2008;neuf;dix un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix $ awk -F";" '$8 !~ /([01][0-9]|2[0-9]|3[01])\/(0[1-9]|1[012])\/[0-9][0-9][0-9][0-9]/ { print "Ligne : "NR" pas OK " $8}' data Ligne : 2 pas OK 5/08/2006 Ligne : 3 pas OK Ligne : 6 pas OK 32/11/2008 Ligne : 7 pas OK 25/1/2009
Pour grep je saute les 1ers 7 champs et je teste sur le 8ème.
Avec grep
$ egrep -vn '^(.*;){7}([01][0-9]|2[0-9]|3[01])\/(0[1-9]|1[012])\/[0-9]{4}' data 2:un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix 3:un;deux;2/5/2009;quatre;cinq;six;sept;;neuf;dix 6:un;deux;trois;quatre;cinq;six;sept;32/11/2008;neuf;dix 7:un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix
Re,
Pour traiter aussi le cas de 00 pour le jour
Pour traiter aussi le cas de 00 pour le jour
$ cat data un;01/1/2010deux;trois;quatre;cinq;six;sept;15/08/2006;neuf;dix un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix un;deux;2/5/2009;quatre;cinq;six;sept;;neuf;dix un;deux;trois;quatre;cinq;six;sept;00/01/2010;neuf;dix un;deux;trois;quatre;7/10/2010;six;sept;31/10/2009;neuf;dix un;deux;trois;quatre;cinq;six;sept;32/11/2008;neuf;dix un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix $ awk -F";" '$8 !~ /(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/[0-9][0-9][0-9][0-9]/ { print "Ligne : "NR" pas OK " $8}' data Ligne : 2 pas OK 5/08/2006 Ligne : 3 pas OK Ligne : 4 pas OK 00/01/2010 Ligne : 6 pas OK 32/11/2008 Ligne : 7 pas OK 25/1/2009 $ egrep -vn '^(.*;){7}(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/[0-9]{4}' data 2:un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix 3:un;deux;2/5/2009;quatre;cinq;six;sept;;neuf;dix 4:un;deux;trois;quatre;cinq;six;sept;00/01/2010;neuf;dix 6:un;deux;trois;quatre;cinq;six;sept;32/11/2008;neuf;dix 7:un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix
Re,
En fait, le | n'est pas accepté par awk pour faire un ou, ni les { } pour utiliser le multiplicateur.Est-ce une limitation de gawk ?
L'alternative fonctionne bien, mais comme j'ai expliqué dans l'exemple précédent il faut grouper les alternative pour obtenir le résultat voulu. Le moteur des regex n'est pas intelligent, ça seul qualité est la persévérance.
Pour le quantificateur intervalle {n,m} dans man awk je vois ça
Interval expressions are only available if either --posix or --re-interval is specified on the command line.
En fait, le | n'est pas accepté par awk pour faire un ou, ni les { } pour utiliser le multiplicateur.Est-ce une limitation de gawk ?
L'alternative fonctionne bien, mais comme j'ai expliqué dans l'exemple précédent il faut grouper les alternative pour obtenir le résultat voulu. Le moteur des regex n'est pas intelligent, ça seul qualité est la persévérance.
Pour le quantificateur intervalle {n,m} dans man awk je vois ça
Interval expressions are only available if either --posix or --re-interval is specified on the command line.
$ cat data un;01/1/2010deux;trois;quatre;cinq;six;sept;15/08/2006;neuf;dix un;deux;trois;quatre;cinq;six;sept;5/08/2006;neuf;dix un;deux;2/5/2009;quatre;cinq;six;sept;;neuf;dix un;deux;trois;quatre;cinq;six;sept;00/01/2010;neuf;dix un;deux;trois;quatre;7/10/2010;six;sept;31/10/2009;neuf;dix un;deux;trois;quatre;cinq;six;sept;32/11/2008;neuf;dix un;deux;trois;quatre;cinq;six;sept;25/1/2009;neuf;dix $ awk --posix -F";" '$8 !~ /(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/([0-9]{4})/ { print "Ligne : "NR" pas OK " $8}' data Ligne : 2 pas OK 5/08/2006 Ligne : 3 pas OK Ligne : 4 pas OK 00/01/2010 Ligne : 6 pas OK 32/11/2008 Ligne : 7 pas OK 25/1/2009 $ awk --re-interval -F";" '$8 !~ /(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/([0-9]{4})/ { print "Ligne : "NR" pas OK " $8}' data Ligne : 2 pas OK 5/08/2006 Ligne : 3 pas OK Ligne : 4 pas OK 00/01/2010 Ligne : 6 pas OK 32/11/2008 Ligne : 7 pas OK 25/1/2009
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
10 déc. 2009 à 20:31
10 déc. 2009 à 20:31
Merci l'AMI pour toutes ces belles explications ;-))
bob031
Messages postés
8158
Date d'inscription
samedi 7 août 2004
Statut
Membre
Dernière intervention
1 septembre 2014
472
10 déc. 2009 à 20:42
10 déc. 2009 à 20:42
Oh oui ... un grand merci !
:-)
:-)