Bonjour,
Je souhaiterais importer dans une base de donnée une classification de villes.
Le fichier .csv est constitué ainsi et non modifiable:
france,"paris","E1"
france,"lyon","E2"
chine,"pekin","A1"
etc...
Je cherche à avoir la nomenclature suivante:
fraparis1
fralyon2
chipekin1
etc...
J'ai écris le script suivant:
#!/bin/sh
#Pour appeler le fichier.
cat villes.csv | while read ligne
do
#Pour extraire chaque élément et les mettre dans des variables différentes.
pays=`echo $ligne | tr -d \" | cut -d',' -f1 | cut -c1-3`
ville=`echo $ligne | tr -d \" | cut -d',' -f2`
num=`echo $ligne | tr -d '"' | cut -d',' -f3`
#Pour trier
tri=`echo $pays | cut -c1-3 && echo $ville && echo $num | tr -d \[A-Z]`
echo $tri
done
Qui me donne le résultat suivant:
fra paris 1
ita rome 1
chi pekin 1
fra lyon 2
per lima 1
esp madrid 1
esp barcelonne 2
Comment supprimer les espaces?
Amitiés à tous les linuxiens et OOoiens
# toujours tr
Posté par errno . Évalué à 3.
# IFS: Input field separator
Posté par Frédéric Perrin (site web personnel) . Évalué à 5.
Non, je plaisante, hein.
info bash "Shell Variables" "Bourne Shell Variables"
IFS permet de dire comment splitter une ligne de texte en lexèmes. Ça te permettra quelque chose de bien plus simple que ce que tu as ici :
#!/bin/bash
IFS=","
cat villes.csv | tr -d \" | while read pays ville num; do
pays=$(echo $pays | cut -c1-3)
num=$(echo $num | tr -d '[A-Z]')
echo "$pays$ville$num"
done
Je n'ai pas compris le commentaire "Pour trier", puisque tu ne tries rien du tout, donc j'ai peut-être loupé quelque chose.
Quoi qu'il en soit : en modifiant IFS, je laisse au shell le soin de splitter la ligne lui-même. Ça évite les | cut -d, -f X. Ensuite, en factorisant la suppression des guillemets, il est plus simple de voir le traitement qui est commun à tous les champs et celui qui diffère à chaque fois. Tu tronquais deux fois $pays à trois caractères, j'ai supprimé ça. J'ai ramené la suppression des lettres de $num en-dehors de l'echo.
Pour revenir à la question initiale, $tri contient après l'exécution de la longue ligne chaque champ, séparés par des retours à la ligne. Quand ton shell lit "echo $tri", avec la valeur par défaut de IFS, il sépare $tri en trois lexèmes, passés en arguments à echo, qui les affiche les uns après les autres séparés par des espaces.
Questions en suspens : que se passe-t-il le jour où une ville contient une virgule, par exemple si tu fais du commerce avec "Paris, Texas" ? Est-on sûrs que le champ $num est toujours de la forme Xn, avec X une lettre et n un unique chiffre ? Que se passe-t-il le jour où quelqu'un ajoute un quatrième champ ? N'y a-t-il pas d'accents sur le nom « Perou » ou « Pekin » ? Pourquoi les habitants de Barcelonne, ce (probablement charmant) village de la Drôme ont-ils fait allégeance à la couronne espagnole ?
# les regex, c'est bien
Posté par Xavier Teyssier (site web personnel) . Évalué à 6.
perl -ne 's/^(.{3}).*"(.*)",".(.)"$/$1$2$3/;print ' /tmp/plop.txt
où /tmp/plop.txt est ton fichier.
Je considère que tu n'auras pas d'autres guillemets que ceux qui entourent les 2° et 3° champs, et que le 3° champs sera toujours constitué de deux caractères...
# Hmmm
Posté par Pascal Terjan (site web personnel) . Évalué à 3.
tri=`echo $pays | cut -c1-3 && echo $ville && echo $num | tr -d '[A-Z]'`
Pourquoi cut -c1-3 vu que tu l'as fait avant ?
Pourquoi des &&
Tu pourrais par exemple faire :
tri=$pays$ville`echo $num | tr -d '[A-Z]'`
Ou mieux, faire le tr -d sur la ligne ou tu generes $num, comme pour les autres
# sed, c'est bien (je l'ai déjà faite, je sais)
Posté par Kerro . Évalué à 4.
sed 's/^(.{3}).*,"(.*)",".(.)"$/\1\2\3/' | sort
Non testé, mais en gros c'est ça.
[^] # Re: sed, c'est bien (je l'ai déjà faite, je sais)
Posté par zerkman (site web personnel) . Évalué à 3.
# en Bash
Posté par NBaH . Évalué à 4.
while IFS="," read pays ville num
do echo "${pays::3}${ville//\"}${num:2:1}"
done <nanard06.csv
fraparis1
fralyon2
chipekin1
# En AWK
Posté par barmic . Évalué à 3.
cat fichier | tr -d \" | awk -F, '{ print substr($1, 1, 3)$2substr($3, 2, length($3)-1) }'
Sinon en pur AWK tu peut créer un fichier pars.awk :
BEGIN{
FS = ","
}
{
sub(/"/, "", $2);
sub(/"/, "", $2);
sub(/"/, "", $3);
sub(/"/, "", $3);
print substr($1, 1, 3)$2substr($3, 2, length($3)-1)
}
Et t'en servir ainsi :
awk -f pars.awk fichier
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: En AWK
Posté par totof2000 . Évalué à 2.
[^] # Re: En AWK
Posté par barmic . Évalué à 2.
On doit plutôt, donc faire ceci :
tr -d \" < fichier | awk -F, '{ print substr($1, 1, 3)$2substr($3, 2, length($3)-1) }
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# Hachage d'un document .csv
Posté par nanard06 . Évalué à 2.
J'ai utilisé IFS et ça fonctionne super (je ne connaissais pas ce truc).
Problème résolu à 100%
# Résultat
Posté par nanard06 . Évalué à 3.
[^] # Re: Résultat
Posté par totof2000 . Évalué à 2.
[^] # Re: Résultat
Posté par barmic . Évalué à 2.
tr -d \" < villes.csv | while read pays ville num; do
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Résultat
Posté par barmic . Évalué à 2.
sed -e 's/^\(.\{3\}\).*,"\(.*\)",".\(.\)"$/\1\2\3/' villes.csv
(Oui il y a de l'antislash)
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Résultat
Posté par Xavier Teyssier (site web personnel) . Évalué à 1.
# En python et en utilisant les libs faites pour
Posté par benoar . Évalué à 2.
Bref, le code, en utilisant csv, en python :
import csv
for line in csv.reader(file("villes.csv")):
print line[0] + line[1] + line[2]
Encore plus lisible que les solutions précédentes.
Et le mieux, c'est que comme tu es dans un vrai langage, tu pourras même utiliser les bindings SQL pour intégrer ça dans ta base ! Genre, après avoir récupéré un curseur "c", mettre dans la boucle :
c.execute("INSERT INTO matable (pays, ville, num) VALUES ?, ?, ?", line)
Voilà, je trouve ça encore plus efficace que les solutions précédentes.
[^] # Re: En python et en utilisant les libs faites pour
Posté par barmic . Évalué à 3.
Ensuite pour ce qui est de l'usage d'un « vrais langage » (j'imagine que ni sed, ni sh, ni awk sont de vrais langages), tu as perl qui peut très bien réussir cette tâche avec un machin du type :
open(CSV, "villes.csv") ¦¦ die ("Erreur d'ouverture de villes.csv");
while(){
$_ =~ /^(.{3}),"(.*)",".(\d*)"$/;
c->execute('INSERT INTO matable (pays, ville, num) VALUES '.$1.', '.$2.', '.$3);
}
Voili voilou
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: En python et en utilisant les libs faites pour
Posté par benoar . Évalué à 4.
Et si, dans le cas où on a un guillemet échappé dans la chaîne ... OK, tu vas me dire, "ça arrivera jamais, aucune ville n'a de guillemet dans son nom", mais "on sait jamais" ... (je ferais bien plus attention aux erreurs de traitement qui pourraient par exemple intégrer un guillemet inséré à cause d'un bug de double échappement ou un truc du genre)
Ma "logique" c'était que tant qu'on a une lib qui suit la "norme" sans se prendre la tête avec les regexp, tout en ayant un langage qui permet d'aussi facilement l'utiliser, autant en profiter.
Enfin, mes excuses pour la pique sur les "vrais langages", c'est vrai que j'ai vu des morceaux de sed et awk assez impressionnant sur ce forum.
[^] # Re: En python et en utilisant les libs faites pour
Posté par barmic . Évalué à 2.
J'avais bien compris et les expressions régulières gèrent parfaitement ces cas là.
Ma "logique" c'était que tant qu'on a une lib qui suit la "norme" sans se prendre la tête avec les regexp, tout en ayant un langage qui permet d'aussi facilement l'utiliser, autant en profiter.
1 000 excuses je ne savais pas du tout d'une part que le format a fait l'objet d'une RFC, d'autre part qu'il existait des bibliothèques pour les gérer.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.