Contenu | Rechercher | Menus

Annonce

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 07/06/2016, à 18:29

waduxair

AWK sur une seule colonne d'un fichier csv

Bonjour à tous,
J'ai un fichier csv se présentant sous cette forme :

"titre1";"titre2";"titre3";"titre4";"titre5";"titre6";"titre7";"titre8"
"1";"2";"3";"4";"5";"6";"7";"8"
"9";"10";"11";"12";"13";"14";"15";"16"

Mon problème est le suivant : la colonne N° 7 comporte des champs de date, mais ces derniers ne sont pas "normalisés". J'ai deux types de dates :

"01-JAN-97"
"02/02/1998"

Le premier exemple a le mois en lettre,en anglais et l'année sur deux chiffres
Le deuxième exemple a le mois en chiffre et l'année sur quatre chiffres

Je souhaiterais que toutes les dates du premier exemple soient transformées au format du second exemple. J'étais parti sur un simple sed qui aurait remplacé les caractères par ceux que je voulais, mais le problème est que certains champs des autres colonnes de mon fichier csv ont les mêmes caractères, par exemple des - ou des champs ayant JAN etc...

L'idée serait donc de faire un traitement sed ou awk, mais uniquement sur la colonne N° 7. Et c'est ici que je bloque. Je n'arrive pas à faire un traitement de données uniquement sur une colonne dans mon fichier csv. J'ai essayé avec un awk, sans succès. Avez-vous des idées afin de résoudre ce problème ?

Merci d'avance pour votre aide.

Dernière modification par waduxair (Le 07/06/2016, à 18:29)

Hors ligne

#2 Le 07/06/2016, à 18:47

littlejohn75

Re : AWK sur une seule colonne d'un fichier csv

waduxair a écrit :

J'ai essayé avec un awk, sans succès. Avez-vous des idées afin de résoudre ce problème ?

Personnellement pour lire un fichier csv  je préfère utiliser python

python
import csv
help(csv)

Cordialement,
Regards,
Mit freundlichen Grüssen,
مع  تحياتي الخالصة
---
F. Petitjean
Tous les nombres premiers sont impairs, sauf un.
Tous les nombres premiers sont impairs, sauf deux.

Hors ligne

#3 Le 07/06/2016, à 18:57

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Bonsoir,
Voici déjà une idée, pour le remplacement des "-" par des "/". Il faudra ensuite compléter la fonction f :

awk -F\; 'function f(s){gsub("-","/",$7)}{f($7);print}' fichier.csv

Hors ligne

#4 Le 07/06/2016, à 20:46

Ferod

Re : AWK sur une seule colonne d'un fichier csv

ça serait pas plus simple de stocker le 7ème champs dans une variable puis d'utiliser la commande date pour faire la conversion ?
Cerise sur le gateau : les dates au bon format ne sont pas modifiées ! big_smile

$ date +%d/%m/%Y -d "25-JUN-06"
25/06/2006
$ date +%d/%m/%Y -d "02/02/1998"
02/02/1998

"When I was in the military, they gave me a medal for killing
two men, and a descharge for loving one !" Leonard Matlovich

Hors ligne

#5 Le 08/06/2016, à 07:12

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

En reprenant l'idée de Ferod :

$ cat fichier.csv
"titre1";"titre2";"titre3";"titre4";"titre5";"titre6";"titre7";"titre8"
"1";"2";"3";"4";"5";"6";"01-JAN-97";"8"
"1";"2";"3";"4";"5";"6";"30-APR-17";"8"
"9";"10";"11";"12";"13";"14";"02/02/1998";"16"
$ awk -F\; -v OFS=\; -v q=\" '{"date +\"%d/%m/%Y\" -d" $7|getline v;if(v)$7=q v q;print}' fichier.csv 2>/dev/null
"titre1";"titre2";"titre3";"titre4";"titre5";"titre6";"titre7";"titre8"
"1";"2";"3";"4";"5";"6";"01/01/1997";"8"
"1";"2";"3";"4";"5";"6";"30/04/2017";"8"
"9";"10";"11";"12";"13";"14";"02/02/1998";"16"

Il y a sans doute plus simple…

Hors ligne

#6 Le 08/06/2016, à 07:53

waduxair

Re : AWK sur une seule colonne d'un fichier csv

La première proposition de pingouinux fonctionne parfaitement pour la modification des - par des /
En revanche, la deuxième méthode reprenant l'idée de Ferod pour la modification des dates ne fonctionne pas de mon côté, les formats de date reste inchangés, j'ai l'impression que le traitement ne s'exécute pas. Je me suis peut être mal pris, j'ai collé les deux lignes de commandes dans un fichier sh (en enlevant le $ au début de la ligne) que j'exécute après.

Hors ligne

#7 Le 08/06/2016, à 08:05

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

waduxair #6 a écrit :

j'ai collé les deux lignes de commandes dans un fichier sh

Il n'y a qu'une seule ligne, et utilise plutôt bash, mais ça ne change rien ici.

Peux-tu montrer un exemple d'un petit fichier qui ne fonctionne pas, ainsi que le script que tu as lancé ?

Hors ligne

#8 Le 08/06/2016, à 08:18

credenhill

Re : AWK sur une seule colonne d'un fichier csv

hello

$ awk 'BEGIN {FS=OFS=";"} $7 ~ /-/ {"date +%d/%m/%Y -d" $7|getline $7} {print} '  fichier.csv
"titre1";"titre2";"titre3";"titre4";"titre5";"titre6";"titre7";"titre8"
"1";"2";"3";"4";"5";"6";01/01/1997;"8"
"1";"2";"3";"4";"5";"6";30/04/2017;"8"
"9";"10";"11";"12";"13";"14";"02/02/1998";"16"

Hors ligne

#9 Le 08/06/2016, à 08:24

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Quel est le retour de cette commande ?

ls -l /usr/bin/*awk* /etc/alternatives/*awk*

Hors ligne

#10 Le 08/06/2016, à 09:07

waduxair

Re : AWK sur une seule colonne d'un fichier csv

La commande retourne ceci :

lrwxrwxrwx 1 root root     13 2016-04-26 18:33 /etc/alternatives/awk -> /usr/bin/gawk
lrwxrwxrwx 1 root root     29 2016-04-26 18:33 /etc/alternatives/awk.1.gz -> /usr/share/man/man1/gawk.1.gz
lrwxrwxrwx 1 root root     13 2016-04-26 18:33 /etc/alternatives/nawk -> /usr/bin/gawk
lrwxrwxrwx 1 root root     29 2016-04-26 18:33 /etc/alternatives/nawk.1.gz -> /usr/share/man/man1/gawk.1.gz
lrwxrwxrwx 1 root root     21 2016-04-26 18:34 /usr/bin/awk -> /etc/alternatives/awk
-rwxr-xr-x 1 root root 307288 2006-04-18 04:48 /usr/bin/gawk
-rwxr-xr-x 1 root root   3089 2006-04-18 04:48 /usr/bin/igawk
-rwxr-xr-x 1 root root  86616 2003-05-30 16:27 /usr/bin/mawk
lrwxrwxrwx 1 root root     22 2016-04-26 18:34 /usr/bin/nawk -> /etc/alternatives/nawk
-rwxr-xr-x 1 root root 307288 2006-04-18 04:48 /usr/bin/pgawk

J'ai testé la commande de credenhill, j'ai le même problème, le traitement ne se fait pas. J'ai collé les commande ci-dessous dans mon terminal et dans les deux cas, j'ai un résultat qui m'affiche tout mon fichier, mais les dates sont inchangées :

awk 'BEGIN {FS=OFS=";"} $7 ~ /-/ {"date +%d/%m/%Y -d" $7|getline $7} {print} '  fichier.csv
awk -F\; -v OFS=\; -v q=\" '{"date +\"%d/%m/%Y\" -d" $7|getline v;if(v)$7=q v q;print}' fichier.csv 2>/dev/null

Hors ligne

#11 Le 08/06/2016, à 09:20

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Je voulais vérifier que tu utilisais bien gawk, et c'est le cas.
On peut vérifier aussi la version. Chez moi, c'est

$ awk --version | head -1
GNU Awk 4.0.1

Peux-tu montrer aussi quelques lignes de fichier.csv dont les dates ne sont pas converties (seul le 7ème champ est intéressant). Les dates sont-elles bien dans le 7ème champ ?

Hors ligne

#12 Le 08/06/2016, à 11:34

credenhill

Re : AWK sur une seule colonne d'un fichier csv

est-ce un fichier Windows avec des ^M ?

cat -A fichier.csv

Hors ligne

#13 Le 09/06/2016, à 07:45

waduxair

Re : AWK sur une seule colonne d'un fichier csv

Pour ce qui est de la version :

awk --version | head -1
GNU Awk 3.1.5

En fait, ce n'est pas quelques dates mais toutes les dates qui ne sont pas converties. Ci-dessous un exemple tiré de mon fichier csv lorsque j'exécute une des commandes. Je viens de me rendre compte que j'ai un message de retour avec le sh :

"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
sh: 19-NOV-95: command not found
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

J'ai testé la commande cat -A fichier.csv, je n'ai pas de ^M.

Dernière modification par waduxair (Le 09/06/2016, à 07:46)

Hors ligne

#14 Le 09/06/2016, à 08:08

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Bizarre ! Problème de version de awk ?

$ cat fichier.csv
"titre1";"titre2";"titre3";"titre4";"titre5";"titre6";"titre7";"titre8"
"1";"2";"3";"4";"5";"6";"01-JAN-97";"8"
"1";"2";"3";"4";"5";"6";"30-APR-17";"8"
"9";"10";"11";"12";"13";"14";"02/02/1998";"16"
"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""
$ awk -F\; -v OFS=\; -v q=\" '{"date +\"%d/%m/%Y\" -d" $7|getline v;if(v)$7=q v q;print}' fichier.csv 2>/dev/null
"titre1";"titre2";"titre3";"titre4";"titre5";"titre6";"titre7";"titre8"
"1";"2";"3";"4";"5";"6";"01/01/1997";"8"
"1";"2";"3";"4";"5";"6";"30/04/2017";"8"
"9";"10";"11";"12";"13";"14";"02/02/1998";"16"
"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
"BOUCHER";"Marie";"001587";"";"";"F";"19/11/1995";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Fais un copier-coller de la commande que tu lances, et de son résultat.

Quel est le retour de

date +"%d/%m/%Y" -d "19-NOV-95"
date --version | head -1

Chez moi

19/11/1995
date (GNU coreutils) 8.21

Édité : Tu peux essayer avec cette commande, qui permet de voir les messages d'erreur. 2>/dev/null supprime le message d'erreur quand la colonne 7 n'est pas une date ("titre7" par exemple).

awk -F\; -v OFS=\; -v q=\" '{"date +\"%d/%m/%Y\" -d" $7|getline v;if(v)$7=q v q;print}' fichier.csv

Dernière modification par pingouinux (Le 09/06/2016, à 09:09)

Hors ligne

#15 Le 09/06/2016, à 09:17

waduxair

Re : AWK sur une seule colonne d'un fichier csv

La commande date me donne bien un bon résultat :

date +"%d/%m/%Y" -d "19-NOV-95"
19/11/1995

Le résultat de cette commande :

date --version | head -1
date (GNU coreutils) 5.97

Les commandes ci-dessous

awk -F\; -v OFS=\; -v q=\" '{"date +\"%d/%m/%Y\" -d" $7|getline v;if(v)$7=q v q;print}' fichier.csv 2>/dev/null

M'affichent un résultat qui correspond exactement au même fichier d'origine, sans aucune modification dans le champ 7 (extrait) :

"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Les commandes ci dessous :

awk 'BEGIN {FS=OFS=";"} $7 ~ /-/ {"date +%d/%m/%Y -d" $7|getline $7} {print} '  fichier.csv

M'affichent un résultat avec l'erreur sh pour chaque date à modifier, voir ci-dessous (extrait) :

"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
sh: 19-NOV-95: command not found
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

EDIT : avec la commande ci-dessous :

awk -F\; -v OFS=\; -v q=\" '{"date +\"%d/%m/%Y\" -d" $7|getline v;if(v)$7=q v q;print}' fichier.csv

Le résultat est :

sh: 01/01/1970: Aucun fichier ou répertoire de ce type
"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
sh: 19-NOV-95: command not found
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Dernière modification par waduxair (Le 09/06/2016, à 09:19)

Hors ligne

#16 Le 09/06/2016, à 09:21

credenhill

Re : AWK sur une seule colonne d'un fichier csv

essayer

awk 'BEGIN {FS=OFS=";"} $7 ~ /-/ {x="date +\"%d/%m/%Y\" -d " $7;x|getline $7} {print} '  fichier

Hors ligne

#17 Le 09/06/2016, à 11:05

waduxair

Re : AWK sur une seule colonne d'un fichier csv

Il me renvoie date invalide sur les dates au format jj-mm--aa :

"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
date: date invalide `19-NOV-95'
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Hors ligne

#18 Le 09/06/2016, à 11:14

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Si ce n'est pas un problème de version, je ne comprends pas.
On peut essayer avec le script python : modif_date.py

import sys, os
for lig in sys.stdin:
   ligspl=lig.split(';')
   dat=os.popen('date +"%%d/%%m/%%Y" -d %s 2>/dev/null'%ligspl[6],'r').read()[:-1]
   if dat: ligspl[6]='"'+dat+'"'
   print(';'.join(ligspl)),

À lancer ainsi :

python modif_date.py <fichier.csv

Hors ligne

#19 Le 09/06/2016, à 11:37

credenhill

Re : AWK sur une seule colonne d'un fichier csv

essayer de voir la commande date exécutée

awk 'BEGIN {FS=OFS=";"} $7 ~ /-/ {x="set -x; date +\"%d/%m/%Y\" -d " $7;x|getline $7} {print} ' fichier

Hors ligne

#20 Le 10/06/2016, à 05:34

waduxair

Re : AWK sur une seule colonne d'un fichier csv

La commande

python modif_date.py <fichier.csv

Me renvoie aucune modification sur le champ de date, j'ai donc un résultat comme ceci :

"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

La commande

awk 'BEGIN {FS=OFS=";"} $7 ~ /-/ {x="set -x; date +\"%d/%m/%Y\" -d " $7;x|getline $7} {print} ' fichier

Reconnaît bien les dates au format jj/mm/aaaa mais il me retourne à nouveau une erreur sur les dates au format jj-mmm-aa :

+ date +%d/%m/%Y -d 01-JAN-70
"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
+ date +%d/%m/%Y -d 19-NOV-95
date: date invalide '19-NOV-95'
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Hors ligne

#21 Le 10/06/2016, à 05:53

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Le programme modif_date.py fait un appel système à la commande date. Je suppose donc que c'est cette dernière qui est en cause.

Pour info, les résultats sont corrects chez moi avec ces versions :

GNU Awk 4.0.1
date (GNU coreutils) 8.21

et

GNU Awk 3.1.8
date (GNU coreutils) 8.13

Je sèche… sad

Ajouté :
Que retourne

type date

Dernière modification par pingouinux (Le 10/06/2016, à 06:02)

Hors ligne

#22 Le 10/06/2016, à 06:53

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

Essayer modif_date2.py

import sys
from time import strftime, strptime

def conv_date(dat):
   try: tup=strptime(dat.strip('"'),"%d-%b-%y")
   except ValueError: return dat
   return strftime('"%d-%m-%Y"',tup)

for lig in sys.stdin:
   ligspl=lig[:-1].split(';')
   ligspl[6]=conv_date(ligspl[6])
   print(';'.join(ligspl))

À appeler ainsi

python modif_date2.py <fichier.csv

Dernière modification par pingouinux (Le 10/06/2016, à 07:00)

Hors ligne

#23 Le 10/06/2016, à 07:39

waduxair

Re : AWK sur une seule colonne d'un fichier csv

Oui, c'est étrange...

J'ai le message ci-dessous pour la commande type date :

type date
date is hashed (/bin/date)

Pour ce qui est du script python v2, aucune modification ni message d'erreurs en retour :

"COUDERT";"Jean";"010209";"";"";"M";"01/01/1970";"TEL_BUREAU";"TEL_PORTABLE";"CH";""
"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-95";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Hors ligne

#24 Le 10/06/2016, à 08:05

credenhill

Re : AWK sur une seule colonne d'un fichier csv

date depuis awk fait-il aussi une erreur avec

"BOUCHER";"Marie";"001587";"";"";"F";"19-NOV-1995";"TEL_BUREAU";"TEL_PORTABLE";"AC";""

Hors ligne

#25 Le 10/06/2016, à 09:23

pingouinux

Re : AWK sur une seule colonne d'un fichier csv

waduxair #23 a écrit :

Pour ce qui est du script python v2, aucune modification ni message d'erreurs en retour :

Qu'il n'y ait pas de message d'erreur, c'est normal, car si le format de la date n'est pas reconnu, elle n'est pas modifiée.

C'est le module time de python qui est utilisé ici, et non la fonction date du système.

À tout hasard (mais je ne vois pas comment ça pourrait jouer pour des mois dont les 3 premières lettres sont identiques en français et en anglais), quel est le retour de

locale

Hors ligne