Remplacement d'éléments d'une liste

Le
titof92
Bonjour,

J'ai un fichier de donnée au format CSV (avec des caractères ; en
guise de séparateurs de valeurs) que je lis en séquentiel. En fait, je
voudrais remplacer le code dossier a figurant en 2e élément dans
l'extrait ci-dessous par le code dossier b, disponible dans ma table
de hachage d'une part, remplacer les dates apparaissant sur chaque en
ligne, en changeant le format pour qu'elles apparaissent en format
AAAAMMJJ au lieu de JJ/MM/AAAA (en évitant toutefois d'utiliser la
fonction S/elt1/elt2/, mais en recourant plutôt à une itération qui
parcourt élégamment chaque élément de @tabligne (résultat du spli=
t ma
ligne)

Je pense qu'il y a sûrement moyen, étant donné que l'indice le plus
faible est 0 (pour le max qui n'est autres que la taille de la liste,
je ne sais pas s'il y a une variable standard Perl déjà disponible
pour l'occaz )

Extrait de mon fichier de données:
233;113456671111;10/12/2011;10/12/2011;M. DUPONT;ERVI;PARIS
456;908289877378:08/05/2001;17;04;2002;Melle DUPRE
Sylvie;ETTY;TOULOUSE
567;356536565365;01/03/1979;09/03/1983;Mme ZANNI Céline;ELSI;SAUMUR

Dans le code qui suit, listeDossiers est une table de hachage dans
laquelle je stocke le résultat d'une requête qui établit la
correspondance entre des codes dossiers a et des codes dossiers b.


# Lecture en séquentiel du fichier reçu
while ($ligne = <FIC_IN>) {

# Prise en compte de la ligne avec separateurs CSV (;)
@tabligne = split(';', $ligne);

print "Ligne en entrée : $ligne ";

# Lecture de toutes les lignes sauf HDR/TRL
if (($ligne ne '') && ($ligne !~ m!^[Hh][Dd][Rr]|^[Tt][Rr][Ll]! )) {
chomp $ligne;

$cdossier_a=$tabligne[2];

# Recherche du code dossier b dans la requête de correspondance
cdossier_b-> cdossier_a
$cdossier_b=$listeDossiers{$cdossier_a};

if (!exists($listeDossiers{$cdossier_a})) {
print FIC_LOG "Le dossier $cdossier_a n'existe pas !";
} else {
$ligne=~ s/$cdossier_a/$cdossier_b/;
print FIC_OUT "$ligne";
}

}

print "Ligne en sortie : $ligne " ;




Merci beaucoup.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Jean-Louis Morel
Le #24101091
Le 21/12/2011 22:39, titof92 a écrit :

J'ai un fichier de donnée au format CSV (avec des caractères ; en
guise de séparateurs de valeurs) que je lis en séquentiel. En fait, je
voudrais remplacer le code dossier a figurant en 2e élément dans
l'extrait ci-dessous par le code dossier b, disponible dans ma table
de hachage d'une part, remplacer les dates apparaissant sur chaque en
ligne, en changeant le format pour qu'elles apparaissent en format
AAAAMMJJ au lieu de JJ/MM/AAAA (en évitant toutefois d'utiliser la
fonction S/elt1/elt2/, mais en recourant plutôt à une itération qui
parcourt élégamment chaque élément de @tabligne (résultat du split ma
ligne)...

Je pense qu'il y a sûrement moyen, étant donné que l'indice le plus
faible est 0 (pour le max qui n'est autres que la taille de la liste,
je ne sais pas s'il y a une variable standard Perl déjà disponible
pour l'occaz ...)

Extrait de mon fichier de données:
233;113456671111;10/12/2011;10/12/2011;M. DUPONT;ERVI;PARIS
456;908289877378:08/05/2001;17;04;2002;Melle DUPRE
Sylvie;ETTY;TOULOUSE
567;356536565365;01/03/1979;09/03/1983;Mme ZANNI Céline;ELSI;SAUMUR




Je ne suis pas sûr d'avoir compris la question (et comme personne
ne répond, je suppose que je ne suis pas le seul dans cette situation).

D'abord, si vous parcourez votre tableau @tabligne avec un indice
variant de 0 à $#tabligne avec une boucle for ce n'est pas élégant
pour un programmeur Perl (ça fait trop programmeur C... ;-)

Pourquoi ne voulez-vous pas convertir directement les dates dans
la chaîne $ligne ?

$ligne =~ s!(dd)/(dd)/(dddd)!$3$2$1!g;

Ou bien, si vous voulez convertir uniquement les dates comprises entre
deux points-virgules (donc pas de date en début et fin de ligne) :

$ligne =~ s!;(dd)/(dd)/(dddd);!;$3$2$1;!g;

HTH

--
JL
http://www.bribes.org/perl
Azra
Le #24108761
Bonjour,
je suis pas certain de comprendre toutes les contraintes du probleme non
plus. Voici une idee de solution pour l'autre probleme [plus simple].

Si vous voulez absolument utiliser split pour modifier la ligne, il est
surement bon d'utiliser un join une fois que vous avez fini de modifier
la ligne et que vous voulez la ``reformer'' en une ligne CSV.
Par ailleurs, il est alors bon de faire les modifications utilisant les
regexps sur la ligne complete soit avant le split soit apres le join !

Ainsi dans votre code
$ligne=~ s/$cdossier_a/$cdossier_b/; # peut -a priori- matcher le premier
# champ de la ligne et le remplacer !
# il faudrait specifier que cdossier_a se trouve
# dans le 2e champ avec s/;$cdossier_a/$cdb/; par
# ex.
devrait se faire remplacer par
$tabligne[2] = $cdossier_b;
$ligne = join ';', @tabligne;


non ?

enfin il y a des chances pour que
$cdossier_b=$listeDossiers{$cdossier_a};
renvoie des warnings [bien penser a utiliser use warnings en tete de
script]
il vaut mieux mettre cette ligne dans votre structure if/else non ???

HTH2
azra

titof92 wrote:

Bonjour,

J'ai un fichier de donnée au format CSV (avec des caractères ; en guise
de séparateurs de valeurs) que je lis en séquentiel. En fait, je
voudrais remplacer le code dossier a figurant en 2e élément dans
l'extrait ci-dessous par le code dossier b, [...]

# Lecture de toutes les lignes sauf HDR/TRL if (($ligne ne '') &&
($ligne !~ m!^[Hh][Dd][Rr]|^[Tt][Rr][Ll]! )) {
chomp $ligne;

$cdossier_a=$tabligne[2];

# Recherche du code dossier b dans la requête de


correspondance
cdossier_b-> cdossier_a
$cdossier_b=$listeDossiers{$cdossier_a};

if (!exists($listeDossiers{$cdossier_a})) {
print FIC_LOG "Le dossier $cdossier_a n'existe


pas !n";
} else {
$ligne=~ s/$cdossier_a/$cdossier_b/;
print FIC_OUT "$lignen";
}

}

print "Ligne en sortie : $ligne nn" ;

...


Merci beaucoup.
Paul Gaborit
Le #24109881
À (at) Wed, 21 Dec 2011 13:39:24 -0800 (PST),
titof92
J'ai un fichier de donnée au format CSV (avec des caractères ; en
guise de séparateurs de valeurs) que je lis en séquentiel.



Au lieu de (mal) réinventer la roue, vous feriez mieux d'utiliser l'un
des deux modules Text::CSV ou Text::CSV_XS. Ils vous garantissent la
lecture et l'écriture correctes des fichiers CSV. C'est une chose plus
difficile à faire qu'il n'y paraît...

Vous pouvez aussi jeter un oeil à DBI et DBD::CSV qui permettent de
manipuler avec des requêtes SQL standard un ensemble de fichiers CSV
considéré comme une base de données.

--
Paul Gaborit - Perl en français -
Publicité
Poster une réponse
Anonyme