[C] extraire partie d'un fichier texte
vincent02
Messages postés
9
Date d'inscription
Statut
Membre
Dernière intervention
-
lami20j Messages postés 21331 Date d'inscription Statut Modérateur, Contributeur sécurité Dernière intervention -
lami20j Messages postés 21331 Date d'inscription Statut Modérateur, Contributeur sécurité Dernière intervention -
Bonjour,
Je dois faire quelque chose qui m'a pas l'air très dur mais malheuresement, je n'ai pas la moindre idée de la manière de procéder,
J'ai un fichier textes composés d'une succession de chaines de caractères comme celle ci :
16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668]
16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]
Mille plus précisément et je souhaite juste extraire 9.50 MB/s et 9.60 MB/s...meme pas dans un tableau, juste récuperer les valeurs...
Je ne connais pas les pointeurs. donc il me faudrait qqchose d'assez simple.
Merci infiniment,
Mon adresse email est vincent_roye@hotmail.com
Je dois faire quelque chose qui m'a pas l'air très dur mais malheuresement, je n'ai pas la moindre idée de la manière de procéder,
J'ai un fichier textes composés d'une succession de chaines de caractères comme celle ci :
16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668]
16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]
Mille plus précisément et je souhaite juste extraire 9.50 MB/s et 9.60 MB/s...meme pas dans un tableau, juste récuperer les valeurs...
Je ne connais pas les pointeurs. donc il me faudrait qqchose d'assez simple.
Merci infiniment,
Mon adresse email est vincent_roye@hotmail.com
A voir également:
- [C] extraire partie d'un fichier texte
- Fichier bin - Guide
- Comment réduire la taille d'un fichier - Guide
- Comment ouvrir un fichier epub ? - Guide
- Fichier rar - Guide
- Extraire une video youtube - Guide
12 réponses
apparement tu as plusieurs chaines de caractères séparées par des espaces blancs.
ce que je te conseille c'est de définir une chaine pour chaque element, douvrir ton fichier et d'effectuer un
fscanf("%s %s %s %s %s %s %s %s ...",nom des tableau correspondant);
apres tu regarde si le tbleau contenant la chaine du debit est equivalente a une chaine fixe.
Si tu ne comprend pas je texpliquerais avec un exemple.
ce que je te conseille c'est de définir une chaine pour chaque element, douvrir ton fichier et d'effectuer un
fscanf("%s %s %s %s %s %s %s %s ...",nom des tableau correspondant);
apres tu regarde si le tbleau contenant la chaine du debit est equivalente a une chaine fixe.
Si tu ne comprend pas je texpliquerais avec un exemple.
Pas d'adresse mail sur le forum s'il vous plaît (enfin moi je dis ça surtout pour toi :p) !
Tu peux aussi faire des trucs de ce genre : tu veux extraire le chiffre 6 dans la chaine "plop 6" :
arth a oublié de passer le fichier en paramètre du fscanf. Tu peux consulter l'aide ici :
http://www.linux-france.org/article/man-fr/man3/scanf-3.html
Tu peux t'inspirer de ce post pour voir comment lire un fichier ligne par ligne :
https://forums.commentcamarche.net/forum/affich-2234751-c-parsing-d-un-fichier
Si tu es motivé tu peux utiliser aussi la lib pcre.
Ceci dit il y a des langages plus adapté que le C/C++ pour parser des fichiers à l'aide d'expressions régulières, comme le python, le ruby, ou le perl...
Bonne chance
Tu peux aussi faire des trucs de ce genre : tu veux extraire le chiffre 6 dans la chaine "plop 6" :
char *str="plop 6"; int x; sscanf(str,"plop %d",&x);
arth a oublié de passer le fichier en paramètre du fscanf. Tu peux consulter l'aide ici :
http://www.linux-france.org/article/man-fr/man3/scanf-3.html
Tu peux t'inspirer de ce post pour voir comment lire un fichier ligne par ligne :
https://forums.commentcamarche.net/forum/affich-2234751-c-parsing-d-un-fichier
Si tu es motivé tu peux utiliser aussi la lib pcre.
Ceci dit il y a des langages plus adapté que le C/C++ pour parser des fichiers à l'aide d'expressions régulières, comme le python, le ruby, ou le perl...
Bonne chance
Salut,
Ceci dit il y a des langages plus adapté que le C/C++ pour parser des fichiers à l'aide d'expressions régulières, comme le python, le ruby, ou le perl...
mamiemando a raison et c'est vraiment simple.
En revanche travailler sur un petit morceau de fichier ce n'est pas evident.
Si je travailler sur tes lignes (j'ai écrit le code à la volée - donc je n'ai pas tester, je le ferai quand j'arriverai à la maison dans 1h30, mais tu peux le faire jusqu'à là)
Je vais affichier seulement le résultat
P.S. Le code ne fonctionne que sur les 2 lignes ou sur le nombre des lignes que la mémoire peut supporter si la structure est toujours la même
Ceci dit il y a des langages plus adapté que le C/C++ pour parser des fichiers à l'aide d'expressions régulières, comme le python, le ruby, ou le perl...
mamiemando a raison et c'est vraiment simple.
En revanche travailler sur un petit morceau de fichier ce n'est pas evident.
Si je travailler sur tes lignes (j'ai écrit le code à la volée - donc je n'ai pas tester, je le ferai quand j'arriverai à la maison dans 1h30, mais tu peux le faire jusqu'à là)
16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668] 16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]
Je vais affichier seulement le résultat
#!/usr/bin/perl # use warnings;use strict; # les lignes je les ajoute dans le script après le token __END__ # je lis __END__ avec le handle DATA et j'affiche a l'écran les valeurs # while (<DATA>){ print "$1\n" if /.*\((.*)\).*/; } __END__ 16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668] 16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]lami20j
P.S. Le code ne fonctionne que sur les 2 lignes ou sur le nombre des lignes que la mémoire peut supporter si la structure est toujours la même
Ceci dit il y a des langages plus adapté que le C/C++ pour parser des fichiers à l'aide d'expressions régulières, comme le python, le ruby, ou le perl...
mamiemando a raison et c'est vraiment simple.
D'autant plus que la solution lui avait déjà été donnée là :
https://forums.commentcamarche.net/forum/affich-2235053-programmation-bash-debutant-recuperer-donne#0
mamiemando a raison et c'est vraiment simple.
D'autant plus que la solution lui avait déjà été donnée là :
https://forums.commentcamarche.net/forum/affich-2235053-programmation-bash-debutant-recuperer-donne#0
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
quoi arth qu'est ce qu'il a arth c'est ma piste qui te plait pas? bah répond plus souven alors ne faiis pas que le ménage.
C'est améliorable en catchant les numéros avec un \d... Idéalement tu peux même écrire ton expression régulière en vérifiant que les numéros passés entre chaque point ne sont pas trop absurdes.
Ceci dit je trouve qu'il serait intéressant de décrire un peu pourquoi l'expression régulière marche même si les généralités doivent déjà figurer dans la base de connaissance... Uniquement dans un but pédagogique ou pour illustrer ces notions avec des exemples concrets.
Bonne chance
Ceci dit je trouve qu'il serait intéressant de décrire un peu pourquoi l'expression régulière marche même si les généralités doivent déjà figurer dans la base de connaissance... Uniquement dans un but pédagogique ou pour illustrer ces notions avec des exemples concrets.
Bonne chance
Salut,
Ceci dit je trouve qu'il serait intéressant de décrire un peu pourquoi l'expression régulière marche même si les généralités doivent déjà figurer dans la base de connaissance... Uniquement dans un but pédagogique ou pour illustrer ces notions avec des exemples concrets.
Je ne sais pas si t'es adressé à moi mais je vais le faire, avec des exemples et aussi dans l'esprit TMTOWTDI
lami20j
Ceci dit je trouve qu'il serait intéressant de décrire un peu pourquoi l'expression régulière marche même si les généralités doivent déjà figurer dans la base de connaissance... Uniquement dans un but pédagogique ou pour illustrer ces notions avec des exemples concrets.
Je ne sais pas si t'es adressé à moi mais je vais le faire, avec des exemples et aussi dans l'esprit TMTOWTDI
lami20j
C'était adressé à qui est motivé pour décrypter une expression regulière de perl... c'est-à-dire pas moi ;)
Re,
j'ai utilisé toujours les 2 lignes données au début de messages.
il y a toujours la posibilité de modifier ou de créer une autre regex.
je n'ai pas non plus imaginé d'autres situations, c'est un peu tard et je suis un peu parreseux.
avec l'espoir que je ne te deçois pas, voilà ce que ça donne mamiemando
j'ai utilisé toujours les 2 lignes données au début de messages.
il y a toujours la posibilité de modifier ou de créer une autre regex.
je n'ai pas non plus imaginé d'autres situations, c'est un peu tard et je suis un peu parreseux.
avec l'espoir que je ne te deçois pas, voilà ce que ça donne mamiemando
#! /usr/bin/perl use warnings;use strict; # toujours je vais utiliser le handle DATA # 1. utilisation de quantificateur gurmand * while (<DATA>){ print "1. $1\n" if /.*\((.*)\).*/; # dans ce cas j'utilise une regex banale # .* prend n'importe quel caractère 0,1 fois ou ...... # en bref en premier temps .* va avaler tout # ensuite sous contrainte va ceder un par un chaque caractère # jusqu'à quand il trouve la 1ère paranthèse # .* entre paranthèse va faire la même chose mais il sera # de ceder aussi la paranthèse fermante # comme ( et ) sont des metacaractères qui servent au groupement et capture # j'ai utilsé \ pour les trouver littéralement # le dernier .* ne sers pas à grand chose (donc on peut s'abstenir) #} #2. utilisation de la classe de caractères \d qui est équivalente avec [0-9] print "2. $1\n" if / \d\d:\d\d:\d\d # regex reconnaît 16:26:28 \s* # ensuite 0,1 ou n'importe combien d'espaces \( # une paranthèse littérale ( # debut du capture, ici la paranthèse = bestiole regex \d\.\d\d\s*MB\/s # reconnaît une chiffre suit d'un point suit de 2 chiffres # de 0,1 ou plusierus espaces suit de M suit de B suit de slash suit de s ) # fin de la capture \)/x; # paranthèse littérale # la regex: /\d\d:\d\d:\d\d\s*\((\d\.\d\d\s*MB\/s)\)/ #le modificateur x permet d'utiliser des espaces # et des commentaires à l'intérieur de regex #3. utilisation de la classe \d avec quantificateurs {x,y} print "3. $1\n" if / \d{1,2}:\d{1,2}:\d{1,2} # regex reconnaît 16:26:28 # {1,2} veut dire 1 ou 2 chiffres \s* # ensuite 0,1 ou n'importe combien d'espaces \( # une paranthèse littérale ( # debut du capture, ici la paranthèse = bestiole regex \d\.\d{1,2}\s*MB\/s # reconnaît une chiffre suit d'un point suit de 2 chiffres # de 0,1 ou plusierus espaces suit de M suit de B suit de slash suit de s ) # fin de la capture \)/x; # paranthèse littérale #le modificateur x permet d'utiliser des espaces # la regex: /\d{1,2}:\d{1,2}:\d{1,2}\s*\((\d\.\d{1,2}\s*MB\/s)\)/ #le modificateur x permet d'utiliser des espaces # et des commentaires à l'intérieur de regex #4. Utilisation d'une classe complementé [^...] print "4. $1\n" if / \( # paranthèse littérale ( # début de la capture [^()]+ # reconnaît au moins une fois tout caractère qui # n'est ni ( ni ) ) # fin de la capture \)/x; # paranthèse littérale #la regex: /\(([^()]+)\)/ #5. utilisation de test avant (?=motif) et test arrière (?<=motif) print "5. $1\n" if / (?<= # début test arrière \( # on cherche en arrière une paranthèse littérale ouvrante ) # fin test arrière (.*) # on capture si en arrière il y une ( et si avant il ya ) (?= # debut test avant \) # on cherche en avant une ) )/x; # fin de test avant # la regex: /(?<=\()(.*)(?=\))/ #6. utilisation d'une variable et substitution (my $tmp = $_) =~ s/.*\(([^()]+)\).*/$1/; # même regex que 4. print "6. $tmp\n"; } __END__ 16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668] 16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]Le résultat
[lamitest@localhost my_perl_script]$ perl mamiemando.pl 1. 9.50 MB/s 2. 9.50 MB/s 3. 9.50 MB/s 4. 9.50 MB/s 5. 9.50 MB/s 6. 9.50 MB/s 1. 9.60 MB/s 2. 9.60 MB/s 3. 9.60 MB/s 4. 9.60 MB/s 5. 9.60 MB/s 6. 9.60 MB/s [lamitest@localhost my_perl_script]$lami20j
Re,
Voilà le script sans commentaires
Voilà le script sans commentaires
#! /usr/bin/perl use warnings;use strict; # toujours je vais utiliser le handle DATA while (<DATA>){ # 1. utilisation de quantificateur gurmand * print "1. $1\n" if /.*\((.*)\).*/; #2. utilisation de la classe de caractères \d qui est équivalente avec [0-9] print "2. $1\n" if /\d\d:\d\d:\d\d\s*\((\d\.\d\d\s*MB\/s)\)/; #3. utilisation de la classe \d avec quantificateurs {x,y} print "3. $1\n" if /\d{1,2}:\d{1,2}:\d{1,2}\s*\((\d\.\d{1,2}\s*MB\/s)\)/; #4. Utilisation d'une classe complementé [^...] print "4. $1\n" if /\(([^()]+)\)/; #5. utilisation de test avant (?=motif) et test arrière (?<=motif) print "5. $1\n" if /(?<=\()(.*)(?=\))/; #6. utilisation d'une variable et substitution (my $tmp = $_) =~ s/.*\(([^()]+)\).*/$1/; # même regex que 4. print "6. $tmp\n"; } __END__ 16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668] 16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]lami20j
Salut,
pour enregister dans un fichier tu peux utiliser une rédirection
perl script.pl > resultat.txt
En ce qui concerne
print "$1\n" if /.*\((.*)\).*/;
Dans perl idiomatique on peut dire tout simplement fait moi ça si la condition est rempli.
Ex.
affiche si nombre plus grand que 1
print if $nombre >1
pour la regex regarde dans le message 11
lami20j
pour enregister dans un fichier tu peux utiliser une rédirection
perl script.pl > resultat.txt
En ce qui concerne
print "$1\n" if /.*\((.*)\).*/;
Dans perl idiomatique on peut dire tout simplement fait moi ça si la condition est rempli.
Ex.
affiche si nombre plus grand que 1
print if $nombre >1
pour la regex regarde dans le message 11
lami20j
Re,
j'ai pensé aussi d'utiliser le mode slurp et l'assertion \G, mais c'était trop tard (ou trop tôt).
j'ai pensé aussi d'utiliser le mode slurp et l'assertion \G, mais c'était trop tard (ou trop tôt).
#! /usr/bin/perl use warnings;use strict; # mode slurp # permet d'avaler le contenu de DATA dans une variable scalaire # ce qui permet l'utilisation de l'assertion \G undef $/; # $/ ou $INPUT_RECORD_SEPARATOR ou $RS # c'est le séparateur d'entrée, par défaut \n # est consulté par la fonction readline, # l'operateur <HANDLE> et la fonction chomp my $txt = <DATA>; # tous le contenu de DATA pos($txt) = 0; # \G est initialisé à 0 while ($txt =~ /\(/g){ print "$1\n" if $txt =~ /\G(.*)\)/; } #/\(/g) detecte une paranthèse ouvrante progressivement # /\G(.*)\)/ # /\G(.*) capture dans $1 ce que je trouve après la paranthèse ovrante # \)/ jusqu'à on rencontre une paranthèse fermante # ce cycle se repete jusqu'à la fin de contenu de $txt __END__ 16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668] 16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]lami20j
Re,
j'ai pensé aussi d'utiliser le mode slurp et l'assertion \G, mais c'était trop tard (ou trop tôt).
#! /usr/bin/perl
use warnings;use strict;
# mode slurp
# permet d'avaler le contenu de DATA dans une variable scalaire
# ce qui permet l'utilisation de l'assertion \G
undef $/; # $/ ou $INPUT_RECORD_SEPARATOR ou $RS
# c'est le séparateur d'entrée, par défaut \n
# est consulté par la fonction readline,
# l'operateur <HANDLE> et la fonction chomp
my $txt = <DATA>; # tous le contenu de DATA
pos($txt) = 0; # \G est initialisé à 0
while ($txt =~ /\(/g){
print "$1\n" if $txt =~ /\G(.*)\)/;
}
#/\(/g) detecte une paranthèse ouvrante progressivement
# /\G(.*)\)/
# /\G(.*) capture dans $1 ce que je trouve après la paranthèse ovrante
# \)/ jusqu'à on rencontre une paranthèse fermante
# ce cycle se repete jusqu'à la fin de contenu de $txt
__END__
16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668]
16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]
lami20j
Merci beaucoup. le probleme est que je ne sais pas comment ouvrir mon fichier texte ou il y a les lignes que veux traiter. Il faut les mettre dans DATA et le fichier est dans le repertoire /home/vincent/amigos/resultado2.txt
je ne sais pas non plus comment je pourrai avoir mon fichier de sortie traité.
merci encore
j'ai pensé aussi d'utiliser le mode slurp et l'assertion \G, mais c'était trop tard (ou trop tôt).
#! /usr/bin/perl
use warnings;use strict;
# mode slurp
# permet d'avaler le contenu de DATA dans une variable scalaire
# ce qui permet l'utilisation de l'assertion \G
undef $/; # $/ ou $INPUT_RECORD_SEPARATOR ou $RS
# c'est le séparateur d'entrée, par défaut \n
# est consulté par la fonction readline,
# l'operateur <HANDLE> et la fonction chomp
my $txt = <DATA>; # tous le contenu de DATA
pos($txt) = 0; # \G est initialisé à 0
while ($txt =~ /\(/g){
print "$1\n" if $txt =~ /\G(.*)\)/;
}
#/\(/g) detecte une paranthèse ouvrante progressivement
# /\G(.*)\)/
# /\G(.*) capture dans $1 ce que je trouve après la paranthèse ovrante
# \)/ jusqu'à on rencontre une paranthèse fermante
# ce cycle se repete jusqu'à la fin de contenu de $txt
__END__
16:26:28 (9.50 MB/s) - `MEGASAVE.tar.gz.14' saved [942668/942668]
16:26:46 (9.60 MB/s) - `MEGASAVE.tar.gz.15' saved [942668/942668]
lami20j
Merci beaucoup. le probleme est que je ne sais pas comment ouvrir mon fichier texte ou il y a les lignes que veux traiter. Il faut les mettre dans DATA et le fichier est dans le repertoire /home/vincent/amigos/resultado2.txt
je ne sais pas non plus comment je pourrai avoir mon fichier de sortie traité.
merci encore