Parsing d'un fichier txt

Résolu/Fermé
anna - 12 sept. 2013 à 11:53
 anna - 12 sept. 2013 à 21:18
Bonjour !
J'ai pour but de récuperer les données d'un fichier texte pour pouvoir par la suite les inserer dans une base de données.
Voici un exemple du type de fichier que je souhaite parser:

ADD NSN:NID=0,SNTID=1003,SNNO="172.20.233.176",SNMSK="255.255.255.240";
ADD NSN:NID=0,SNTID=112,SNNO="10.33.0.0",SNMSK="255.255.192.0";


ADD ONF:OOFCN="27",RGLEXP="(sip:|tel:)(\\+421)([0-9]*)\;npdi\;rn=(\\+421BB00)(@sip.osk.com\;user=phone){0,1}",RPLEXP="sip:\\4\\***@***\;user=phone",PRIVACYFLAG=N,RESERVED1=0,RESERVED2=0,RESERVED3=0,RESERVED4=0;

le format de chaque ligne est le suivant :

Action<Space>Object: parameter1 = value1,parameter2 = value2,parameter3 = value3;

les parametres sont séparés par des "," et chaue ligne de termine par ";"

on peut trouver des ";" ou ":" ou "," dans une valeur value,mais dans ce cas là , elle sera rangé dans des " ", comme dans la 3ieme ligne.

des fois on trouve des valeur avec les " " , et des fois non.



Le probleme c'est que je suis débutante en perl , et je ne sais pas écrire la chaine de recherche correspondante ..

Voila, si quelqu'un à une idée.

merci d'avance
A voir également:

1 réponse

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
12 sept. 2013 à 17:01
Salut Anna,

On peut parser chaque ligne en deux fois.

Par exemple, pour la 1ère ligne :

- tout d'abord le début de ligne pour matcher jusqu'à "ADD NSN:"
- le reste de la ligne correspond à des couples paramètre = valeurs avec des virgules ou un point-virgule pour les délimiter, et valeurs pouvant être entre guillemets. Ce pattern peut être répété dans une 2ème regexp avec le modificateur g pour récupérer tout cela dans un tableau.

Ce code fonctionne avec l'exemple de données que tu fournis :

#!/usr/bin/perl

use strict;
use warnings;

my $data = q(
ADD NSN:NID=0,SNTID=1003,SNNO="172.20.233.176",SNMSK="255.255.255.240";
ADD NSN:NID=0,SNTID=112,SNNO="10.33.0.0",SNMSK="255.255.192.0";


ADD ONF:OOFCN="27",RGLEXP="(sip:|tel:)(\\+421)([0-9]*)\;npdi\;rn=(\\+421BB00)(@sip.osk.com\;user=phone){0,1}",RPLEXP="sip:\\4\\***@***\;user=phone",PRIVACYFLAG=N,RESERVED1=0,RESERVED2=0,RESERVED3=0,RESERVED4=0;
);

# we turn $data into a file handle,
# so that the while loop looks like yours
open my $FICH, '<', \$data;
while (<$FICH>) {
chomp;
if (/^([A-Z]+)\s([A-Z]+):/)
{
# we have the begining of the line
print "Action = $1 - Object = $2\n";
# process rest of line
$_ = $';
my @list = /([A-Z0-9]+)=(".+?"|.*?)[,;]/g;
if (@list)
{
# splice it, so we can iterate throught every couple of values
while (my ($p,$v) = splice(@list,0,2))
{
print "$p=$v\n";
}
} else
{
# error, we don't have the rest of the line
# do something about this
}
print "-----------\n";
} else
{
# we ignore blank lines of lines which beginning
# does not match
}
}
J'ai supposé que action et objet sont composés de lettres majuscules.

Cela donne :

Action = ADD - Object = NSN
NID=0
SNTID=1003
SNNO="172.20.233.176"
SNMSK="255.255.255.240"
-----------
Action = ADD - Object = NSN
NID=0
SNTID=112
SNNO="10.33.0.0"
SNMSK="255.255.192.0"
-----------
Action = ADD - Object = ONF
OOFCN="27"
RGLEXP="(sip:|tel:)(\+421)([0-9]*)\;npdi\;rn=(\+421BB00)(@sip.osk.com\;user=phone){0,1}"
RPLEXP="sip:\4\***@***\;user=phone"
PRIVACYFLAG=N
RESERVED1=0
RESERVED2=0
RESERVED3=0
RESERVED4=0
-----------

Note que selon https://perldoc.perl.org/perlvar#$%27 l'usage de $' pour retourner la partie de la ligne postérieure à ce qui a été matché va ralentir le moteur de regexp.

Si tu as besoin d'optimiser ton code, tu peux, comme recommandé ici https://perldoc.perl.org/perlvar#@-, utiliser
$_ = substr($_, $+[0])
en lieu et place.


Dal
0
Bonjour Dal,

merci bien pour ton aide , c'est exactement le résultat qu'il me faut.
0