Récupérer plage de donnée [Résolu/Fermé]

Signaler
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016
-
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016
-
Bonjour à tous,
Alors un peu dans le meme genre que mon post précédent, que j'ai fini par réussir à améliorer, je me trouve devant un nouveau problème.

Alors ici dans un programme je cherche plusieurs informations.
Ces informations sont contenus dans un fichier assez lourd. Les données utiles se trouvent entre "DONNEES GENERALES" et "COMMENTAIRES LIBRES" (dans ce sens).
Je dois récupérer plusieurs informations.

Données que je recherche (infine partie du programme):



DONNEES GENERALES
-----------------


CENTRALE....................: XXX
TRANCHE.....................: X
CYCLE.......................: X
EPUISEMENT MOYEN............: AAAA Mwj/T
PUISSANCE NOMINALE..........: XXX
PUISSANCE RELATIVE..........: AAAA
BORE SOLUBLE................: AAAA
MODE DE PILOTAGE............: X
ENFONCEMENT DES GRAPPES (pas extraits)
G1 .......... AAA
G2 .......... AAAA
N1 .......... AAAA
N2 .......... AAAA
R .......... AAAA




COMMENTAIRES LIBRES
-------------------


Ce que je cherche c'est les données illustré par A ici.


Et j'ai pensé à faire ça (mais ça marche pas).
J'ai utilisé l'opérateur d'intervalles mais c'est la première fois...

if( -e "$home/etudes/$Site/$Tranche/$nom/occ1/listing"){
open(TRAITEMENT,"$home/etudes/$Site/$Tranche/$nom/occ1/listing"); ##On ouvre notre fichier

if(/GENERALES/ ... /COMMENTAIRES/)
{@donne=<TRAITEMENT>;
}
else{
print "Plage de donnee non trouvee pour $nom\n";
}}
close(TRAITEMENT);

$n=$#donne;
for($k=0;$k<$n;$k++){
if("@donne" =~/RELATIVE/){
@pivot=grep{$_=~/RELATIVE/} @donne;
@pivot=split(':',$pivot[0]);
$relative=$pivot[1];
}else{
print "Valeur de la Puissance relative non trouvee pour $nom\n";
}

if("@donne" =~/BORE/){
@pivot=grep{$_=~/BORE/} @donne;
@pivot=split(':',$pivot[0]);
$bore=$pivot[1];
}else{
print "Valeur du Bore soluble non trouvee pour $nom\n";
}

if("@donne" =~/EPUISSEMENT/){
@pivot=grep{$_=~/EPUISSEMENT/} @donne;
@pivot=split(':',$pivot[0]);
$bu=$pivot[1];
}else{
print "Valeur du BU non trouvee pour $nom\n";
}

if("@donne" =~ /G1/){
@pivot=grep{$_=~/G1/} @donne;
@pivot=split('..........',$pivot[0]);
$G1=$pivot[1];
}else{
print "Valeur de G1 non trouvee pour $nom\n";
}

if("@donne" =~ /G2/){
@pivot=grep{$_=~/G2/} @donne;
@pivot=split('..........',$pivot[0]);
$G2=$pivot[1];
}else{
print "Valeur de G2 non trouvee pour $nom\n";
}

if("@donne" =~ /N1/){
@pivot=grep{$_=~/N2/} @donne;
@pivot=split('..........',$pivot[0]);
$N1=$pivot[1];
}else{
print "Valeur de N1 non trouvee pour $nom\n";
}

if("@donne" =~ /N2/){
@pivot=grep{$_=~/N2/} @donne;
@pivot=split('..........',$pivot[0]);
$N2=$pivot[1];
}else{
print "Valeur de N2 non trouvee pour $nom\n";
}


if("@donne" =~ /R/){
@pivot=grep{$_=~/R/} @donne;
@pivot=split('..........',$pivot[0]);
$R=$pivot[1];
}else{
print "Valeur de R non trouvee pour $nom\n";
}
}

}else{
print "Le Fichier Listing n'existe pas pour le fichier $nom \n";
}


### On enlève tous les carractères non désirables
($relative=$relative)=~ s/\D*\W*\s*//g;
($bore=$bore)=~ s/\D*\W*\s*//g;
($bu=$bu)=~ s/\D*\W*\s*//g;
($G1=$G1)=~ s/\D*\W*\s*//g;
($G2=$G2)=~ s/\D*\W*\s*//g;
($N1=$N1)=~ s/\D*\W*\s*//g;
($N2=$N2)=~ s/\D*\W*\s*//g;
($R=$R)=~ s/\D*\W*\s*//g;

print "Valeur Relative $relative \n";
print "Valeur bore $bore \n";
print "Valeur BU: $bu \n";
print "valeur position grappe: G1 $G1 G2 $G2 N1 $N1 N2 $N2 R $R \n";

}

7 réponses

Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

Désolé du double post mais je sais pas si j'ai été clair...


J'ai abondonné l'idée sur les opérateurs d'intervalles, je trouve très peu de document mise à part un bouquin que j'ai sous la main.
Je continue avec une à la palce sans réussite
for($m=0;$m<$M;$m++){
if($com[$m]=~/GENERALES/){
while($com[$m]=~/COMMENTAIRES/){
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

Alors j'ai avancé et j'ai réusis !

J'ai utilisé:
@donne=grep{$_=~/DONNEES GENERALES/ ... /COMMENTAIRES/}@com;

Donc j'arrive à récupérer la plage de donnée que je voulais. Pour les valeurs qui sont précédé de ":" j'arrive à les extraire.

Le seul problème c'est pour les autres, ceux précédé par ".......... " (5 dernières valeurs).

J'ai essayé avec :

if("@donne" =~ /G1/){
@pivot=grep{$_=~/G1/} @donne;
@pivot=split('..........',$pivot[0]);
$G1=$pivot[1];
}else{
print "Valeur de G1 non trouvee pour $nom\n";
}

et ça marche pas.... Vous avez des idées svp ?
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
Salut Akre66,

Les points dans le premier argument de split doivent être échappés si tu veux matcher des points. Autrement le
.
signifie : tout caractère.

Donc cela donnerait quelque chose comme :

@pivot=split('\.\.\.\.\.\.\.\.\.\.',$pivot[0]);


Mais utiliser split pour faire ce que tu fais est inadapté.

Ce que je ferai, c'est faire de ton tableau un scalaire avec join et d'y appliquer une regexp unique avec le modificateur
s
pour capturer à travers les lignes ce qui t'intéresse entre "DONNEES GENERALES" et "COMMENTAIRES LIBRES".

Cela tient en une seule regexp et en deux lignes avec la ligne appliquant le join.


Dal
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
c'était quoi ton navigateur ?

La regexp décrit les données selon le format attendu et précise les données à capturer avec les parenthèses. Si la regexp matche, les données capturées correspondant aux parenthèses sont disponibles dans les variables spéciales $1, $2, etc.

par exemple :

.*\s+DONNEES\sGENERALES.*EPUISEMENT\sMOYEN\.+:\s+([^\s]+)


-
.*
: n'importe quel caractère présent 0 ou plusieurs fois
-
\s+
: suivi d'un ou plusieurs caractères blancs (espaces, tabulations ou retours à la ligne)
-
DONNEES\sGENERALES.*EPUISEMENT\sMOYEN
: suivi de "DONNEES GENERALES" de n'importe quel caractère présent 0 ou plusieurs fois puis de "EPUISEMENT MOYEN"
-
\.+:\s+
: suivi d'un ou plusieurs points, suivi de ":", suivi d'un ou plusieurs espaces
-
([^\s]+)
: capturer un ou plusieurs caractères à la suite qui ne sont pas un caractère blanc

L'expression n'est pas faite automatiquement, mais sur la base de mon interprétation de ce qui constitue des points de repère pertinents dans ton format.

L'apprentissage des regexp peut se faire progressivement. Commence par des choses simples.

La doc Perl est utile et bien faite : https://perldoc.perl.org/perlretut

Un outil du type de http://www.weitz.de/regex-coach/ te permet de tester ta regexp à mesure que tu la crées, la vérifier pas à pas, etc. Il y en a d'autres. Si tu l'utilises, pense à remercier son auteur en lui faisant une donation. Il a fait un travail remarquable. La version Windows fonctionne bien sous Linux avec wine (la version Linux est ancienne et malheureusement plus supportée par l'auteur).


Dal
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
Les crochets permettent de spécifier une classe de caractères, ici on procède par négation (le ^ au début de la description de la classe de caractères opère une négation de ce qui figure dans les crochets). J'ai fait ainsi car tu te contentais de décrire les informations avec les caractères "AAAA" sans dire en quoi ils devaient réellement consister.

Tu peux aussi procéder positivement. Tu dis que les "AAAA" sont, en fait, des informations numériques. Si on suppose qu'il ne s'agit que de chiffres, sans virgule ni point, ta capture pourrait utiliser la classe suivante :
([0-9]+)
signifiant tout caractère de 0 à 9 présent à la suite une ou plusieurs fois ou, en plus concis et plus complet :
([\d+)
.


Dal
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

A oui habile !
Je comprends bien.

Je vais essayer d'exploiter ça.
Merci pour tout Dal !
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

Par contre si DONNEES GENERALES est suivi par des espaces et des "-" ça marche pas non ?

Je peux faire un greep dans le fichier pour prélever cette plage avec:

@donne=grep{$_=~/DONNEES GENERALES/ ... /COMMENTAIRES/}@com;

Puis utiliser regexp mais à partir directement de PUISSANCE RELATIVE.
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
dans tes données d'exemple, ton premier "AAAA" figure à "EPUISEMENT MOYEN" pas à "PUISSANCE RELATIVE".

la regexp ignore ce qui est est entre "DONNEES GENERALES" et "EPUISEMENT MOYEN", puisqu'il y a
.*
entre les deux. Il peut y avoir n'importe quoi, ou même rien du tout, la regexp proposée matchera.

le grep est inutile, à mon sens.


Dal
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

J'ai compris (enfin je crois), je l'ai appliqué et ça marche.

Après on m'a demandé de sortir plus d'informations.
Parfois mais pas tout le temps il y a plus d'informations entre "Données générales" et "Commentaires libres".
Puis parfois les commentaires libres sont remplis et contient des valeurs plus juste pour l'épuissement, le bore et R.

Exemple type(modèle qui ressort souvent)
DONNEES GENERALES
-----------------


CENTRALE....................: XXXX
TRANCHE.....................: X
CYCLE.......................: XX
EPUISEMENT MOYEN............: AAAA Mwj/T
PUISSANCE NOMINALE..........: XXXX Mwth
PUISSANCE RELATIVE..........: AAA %
BORE SOLUBLE................: AAAA ppm
MODE DE PILOTAGE............: G
ENFONCEMENT DES GRAPPES (pas extraits)
G1 .......... AAA
G2 .......... AAA
N1 .......... AAA
N2 .......... AAA
R .......... AAA
!! ATTENTION !!
POUR LES CPY, LES VALEURS RENSEIGNEES POUR LES GROUPES DE COMPENSATION DE PUISSANCE DOIVENT ETRE
VERIFIEES (AU MOYEN DES COMMENTAIRES OU D'UNE SOURCE EXTERNE) SI AU MOINS UN DES GROUPES EST DONNE INSERE

NUMERO DE CARTE.............: XX


CETTE CARTE CONTIENT BBB TRACES REPARTIES EN 15 PASSAGES,

ELLE A ETE CREEE LE 10/11/94 A 09:00.


N.B. LES DONNEES GENERALES PROVIENNENT DE LA CARTE LUE, EVENTUELLEMENT MODIFIEES OU COMPLETEES PAR L'UTILISATEUR.

CENTRALE DE XXXXX TRANCHE X CYCLE X BURNUP X CARTE NUMERO X PAGE X

COMMENTAIRES LIBRES
-------------------


NO: XX
DU: CC/CC/CC
TRAN: X
CAMP: XX
IRRA: AAAA MWJ/T
CB: AAA PPM
D: AAA





$
















CENTRALE DE XXXXX TRANCHE X CYCLE X BURNUP X CARTE NUMERO X PAGE X

MOYENNES DES VALEURS CARACTERISTIQUES DE PASSAGE (NaN INDIQUE UNE MESURE NON VALIDE)
------------------------------------------------

(fin)
A peuvent des décimaux comme des entiers.
Suivi de date (CC/CC/CC) est une date.
BB est entier mais se trouve dans une chaine.

Du coup suivi de ton modèle j'ai fait ça...La première qui est la tienne marche. Quand je l'essaye ça marche pas.

if(/.\s+DONNEES\sGENERALES.*EPUISEMENT\sMOYEN\.+:\s+([^\s]+)
.*PUISSANCE\sRELATIVE\.+:\s+([^\s]+)
.*BORE\sSOLUBLE\.+:\s+([^\s]+)
.*G1\s+\.+\s+([^\s]+)
.*G2\s+\.+\s+([^\s]+)
.*N1\s+\.+\s+([^\s]+)
.*N2\s+\.+\s+([^\s]+)
.*R\s+\.+\s+([^\s]+)

.*\s+COMMENTAIRES\sLIBRES/xs){


$bu=$1;
$relative=$2;
$bore=$3;
$G1=$4;
$G2=$5;
$N1=$6;
$N2=$7;
$R=$8;



}else{
print "Plage de donnée 1 pas trouvée\n";
}

if(/.\s+COMMENTAIRES\sLIBRES.*DU:\s+([^\s]+)
.*IRRA:\s+([^\s]+)
.*CB:\s+([^\s]+)
.*D:\s+([^\s]+)
.*\s*MOYENNES\sDES\sVALEURS\sCARACTERISTIQUES\sDE\sPASSAGE/xs){

$date=$1;
$bu=$2;
$bore=$3;
$R=$4;


}else{
print "Plage de donnée 2 pas trouvée\n";
}

je voulais savoir où était mon erreur (et me l'expliquer) dans la deuxième boucle if... Je me dis que peut etre je peux pas utiliser deux fois "Commentaires libres" (une sortie et une entrée) de la boucle if.
Mais si je fais tous dans la meme boucle et que le commentaires libres est vide (ça arrive) ca marcherait pas.

Aussi je voulais savoir comment récupérer les informations contentus dans une chaine de carractère grace à cette boucle if.


Enfin bref je suis perdu...
Merci beaucoup
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

J'ai trouvé mon erreur...
Je faisais un grep avant (car sinon ça marchait pas trop) et j'avais oublié d'agrandirl'ensemble.

J'ai donc tout sauf le "BB" qui se trouve dans une phrase...
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
Oui, j'ai testé ta 2ème regexp et elle fonctionne bien.

Tu peux appliquer autant de tests que tu veux sur les mêmes données de départ, tant que $_ n'est pas modifié.

Stp, quand tu postes des données, c'est important que tu les mettes dans des balises "code" :

<code>
    Données ici
------------
</code>

pour que l'on sache exactement comment sont structurées tes lignes. Sinon le html écrase les espaces vides.

Pour capturer les données BBB, consistant en des valeurs numériques entières se trouvant dans "CETTE CARTE CONTIENT BBB TRACES REPARTIES EN 15 PASSAGES", tu peux modifier la 1ère regexp pour capturer une 9ème donnée en insérant le motif suivant en avant-dernière ligne :

    .*CETTE\sCARTE\sCONTIENT\s([0-9]+)\sTRACES\sREPARTIES\sEN\s[0-9]+\sPASSAGES



Dal
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
hmm, à la réflexion, tu dis :

Parfois mais pas tout le temps il y a plus d'informations entre "Données générales" et "Commentaires libres".

si cela veux dire que la ligne "CETTE CARTE CONTIENT BBB TRACES REPARTIES EN 15 PASSAGES" peut ne pas de trouver dans ta 1ère partie, la 1ère regexp va échouer lorsque cette ligne ne s'y trouve pas.

Donc, le plus simple serait d'utiliser une regexp séparée pour vérifier si cette partie contient, ou non, cette ligne.

Il faut penser que tes regexp sont non seulement un moyen de capture de l'information, mais aussi un moyen de validation de la structure attendue.


Dal
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
Note aussi que tu commence tes regexp ainsi :

if(/.\s+


ce qui veux dire : n'importe quel caractère une fois, suivi de caractères blancs une ou plusieurs fois.

ce n'est pas tout à fait ce que j'avais écrit au départ, même si cela ne semble pas avoir d'impact sur tes données.

ma regexp commençait ainsi :

if (/.*\s+


ce qui veux dire : n'importe quel caractère zéro ou plusieurs fois, suivi de caractères blancs une ou plusieurs fois.

cela permet de matcher la section qui t'intéresse même s'il y a des informations parasites avant.


Dal
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

Et j'ai trouvé pour l'autre...
rien ne changeait, on s'en moque un peu de ce qu'il y a derrière comme le programme.
Tout marche comme sur des roulettes merci
Messages postés
5528
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
5 mai 2021
933
ok, bravo :-)
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

Bonjour,
Je cherche à developper un nouveau script. Il devra un moment préléver toutes les données (issus du programme fait plus haut) pris entre deux "titres" avant de passer à la porchaine plage donnée

Exemple:
Titre N (soit $Titre[$n])
AAAAA
AAAAA
....
AAAA
Titre N+1 (soit $Titre[$n+1])



Les titres sont déjà écris dans un tableau.

Je pense donc à réaliser un grep entre ces deux titres.

@sortie=grep{$_=~/$T[$n]/.../$Titre[$n+1]/}@entree;


Vous en pensez quoi ?
Messages postés
55
Date d'inscription
mercredi 14 mai 2014
Statut
Membre
Dernière intervention
4 octobre 2016

Donc ça marche mais le soucis c'est pour le dernier...

Je pense faire une condition pour ce cas, mais comment lui faire comprendre que c'est le dernier (soit que n+1 n'existe pas) ?