#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
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 !
$ 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
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…
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
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