Extraction de lignes particulières d'un fichier
Tags :
Dernière réponse : dans Le monde de Linux
Bonjour,
j'ai un fichier (.log) dans lequel en gros j'ai des patterns de données par exemple de 4 lignes :
1.blablabla texte
2.données 1
3.données 2
4.ligne vide
5.blablabla texte
6.données 1
7.données 2
8.ligne vide
9.etc...
bref j'ai des tas de ligne et ce que je voudrais c'est extraire par exemple une ligne sur 4 à partir de la 2e ligne pour placer toutes les données 1 (ou données2, et même le texte) du pattern dans un fichier txt par exemple.
(En fait même l'idéal, plutôt que de faire 3 scripts pour récupérer les 3 lignes à chaque fois dans 3 fichiers différents puis de les concaténer avec paste ensuite, ce serait de faire ça en une fois dans mon script)
Et là je bloque, j'ai regardé sur le net sur d'autres forums pour tenter de m'inspirer d'utilisation de fonctions genre awk ou grep mais je n'arrive pas à les utiliser de façon à faire ce que je souhaite faire.
Voici un extrait de mon script (mais qui en plus n'est pas reconnu, quand je le lance ça me fait une erreur "command not found") :
testscript
ou aussi j'ai tenté une une version alternative mais qui ne marche pas non plus :
je précise que quand je le lance je suis dans le répertoire où il est, que je l'ai rendu exécutable en faisant "chmod a+x testscript".
Le 194 c'est parce que y'a 194 patterns de 4 lignes, donc j'ai voulu boucler ça mais je suis pas sûr de m'y être bien pris.
Mon fichier log si ça peut vous aider ressemble à ça :
Ce que je voudrais faire pour résumer donc, c'est créer un fichier de 3 colonnes et 194 lignes contenant :
- en 1ere colonne le nom du fichier traité (donc là je suppose que je dois boucler un cut -c en précisant d'où à où je coupe de sorte à ne pas garder les "[" ainsi que la date et le reste des caractères non désirés, ou alors un grep?)
- en 2e colonne une donnée particulière de la 2e ligne (par exemple la 3e donnée, là aussi je vais de voir utiliser un cut je pense, ou un awk même puisqu'elles sont déjà en colonnes)
- en 3e colonne idem une donnée particulière entre parenthèses de la 3e ligne, par exemple la 3e donnée aussi si je décide de sélectionner la 3e sur la ligne du dessus
Voilà en gros mon problème, dans les scripts que j'ai commencé à faire je me contentais d'abord d'essayer d'extraire une ligne particulière, alors déjà que je n'y suis pas arrivé je n'ai pas encore essayé de faire le reste, mais si vous avez des pistes cela m'aiderait beaucoup !
merci d'avance de votre aide et n'hésitez pas à me redemander des trucs si je n'ai pas été assez clair ou pas assez complet
Julien
j'ai un fichier (.log) dans lequel en gros j'ai des patterns de données par exemple de 4 lignes :
1.blablabla texte
2.données 1
3.données 2
4.ligne vide
5.blablabla texte
6.données 1
7.données 2
8.ligne vide
9.etc...
bref j'ai des tas de ligne et ce que je voudrais c'est extraire par exemple une ligne sur 4 à partir de la 2e ligne pour placer toutes les données 1 (ou données2, et même le texte) du pattern dans un fichier txt par exemple.
(En fait même l'idéal, plutôt que de faire 3 scripts pour récupérer les 3 lignes à chaque fois dans 3 fichiers différents puis de les concaténer avec paste ensuite, ce serait de faire ça en une fois dans mon script)
Et là je bloque, j'ai regardé sur le net sur d'autres forums pour tenter de m'inspirer d'utilisation de fonctions genre awk ou grep mais je n'arrive pas à les utiliser de façon à faire ce que je souhaite faire.
Voici un extrait de mon script (mais qui en plus n'est pas reconnu, quand je le lance ça me fait une erreur "command not found") :
testscript
#! /bin/bash
for i in 'seq 1 194' ;
x=4*i - 1
do
awk 'NR==x' fichier.log > données1.txt
done
ou aussi j'ai tenté une une version alternative mais qui ne marche pas non plus :
awk ' BEGIN
{
for (i=1;i<=194;i++)
{
x=i*4 - 1
print $x
}
}
END ' /home/chemin/fichier.log > données1.txt
je précise que quand je le lance je suis dans le répertoire où il est, que je l'ai rendu exécutable en faisant "chmod a+x testscript".
Le 194 c'est parce que y'a 194 patterns de 4 lignes, donc j'ai voulu boucler ça mais je suis pas sûr de m'y être bien pris.
Mon fichier log si ça peut vous aider ressemble à ça :
Apr 15 11:49 [nomdufichiertraité1.fits[*,1]]:
1974.419 1.117 -1.26 1.126 -1.62 73.02 0.
( 764.87) ( ) (9.4) ( 8.427) (2.7) ( 395.4) ( 0.)
Apr 15 11:49 [nomdufichiertraité2.fits[*,1]]:
1984.702 1.265 -8.55 0.676 -9.72 8.268 0.
( 1.6385) ( ) (3.2) ( 0.2504) (3.6) ( 4.219) ( 0.)
etc...
Ce que je voudrais faire pour résumer donc, c'est créer un fichier de 3 colonnes et 194 lignes contenant :
- en 1ere colonne le nom du fichier traité (donc là je suppose que je dois boucler un cut -c en précisant d'où à où je coupe de sorte à ne pas garder les "[" ainsi que la date et le reste des caractères non désirés, ou alors un grep?)
- en 2e colonne une donnée particulière de la 2e ligne (par exemple la 3e donnée, là aussi je vais de voir utiliser un cut je pense, ou un awk même puisqu'elles sont déjà en colonnes)
- en 3e colonne idem une donnée particulière entre parenthèses de la 3e ligne, par exemple la 3e donnée aussi si je décide de sélectionner la 3e sur la ligne du dessus
Voilà en gros mon problème, dans les scripts que j'ai commencé à faire je me contentais d'abord d'essayer d'extraire une ligne particulière, alors déjà que je n'y suis pas arrivé je n'ai pas encore essayé de faire le reste, mais si vous avez des pistes cela m'aiderait beaucoup !
merci d'avance de votre aide et n'hésitez pas à me redemander des trucs si je n'ai pas été assez clair ou pas assez complet
Julien
Autres pages sur : extraction lignes particulieres fichier
Lassé par la pub ? Créez un compte
- | Alerter
- | Alerter
- | Alerter
Contenus similaires
- Fichier de script - Forum
- Linux creation de script - Forum
- Créer un script linux - Forum
- Exécuter script php - Forum
merci pour vos réponses !
sinon oui là je me sens bien stupide : l'habitude Matlab d'exécuter les scripts juste en tapant le nom, j'avais bel et bien oublié de taper le ./ avant le nom...
pour les balises "code" j'avais pas vu désolé, je vais y faire attention maintenant !
je vais voir tout ça d'ici demain car là j'ai pas trop le temps et je vous tiens au courant assez rapidement alors
sinon oui là je me sens bien stupide : l'habitude Matlab d'exécuter les scripts juste en tapant le nom, j'avais bel et bien oublié de taper le ./ avant le nom...
pour les balises "code" j'avais pas vu désolé, je vais y faire attention maintenant !
je vais voir tout ça d'ici demain car là j'ai pas trop le temps et je vous tiens au courant assez rapidement alors
- | Alerter
- | Alerter
@ Zeb : alors j'ai essayé ton petit script awk et là en fait ça me créé juste des fichiers qui sont nommés en fonction de I qui croit jusqu'à ce que j'arrête de faire tourner le script.
J'ai donc remarqué que dans mes scripts il fallait des instructions dans le BEGIN et END, ce que j'avais oublié de faire.
J'ai tenté ça :
mais ça me retourne une erreur de syntaxe, je vois pas trop comment arriver à extraire ces lignes, comment gérer la sélection à partir de mon opération basique x=4*I-1 par exemple.
J'ai donc remarqué que dans mes scripts il fallait des instructions dans le BEGIN et END, ce que j'avais oublié de faire.
J'ai tenté ça :
awk ' BEGIN {I=1}
{
x=(I*4)-1
{ print $x : I++ }
}
END{I<=194} ' /home/chemin/fichier.log > fichier.txt
mais ça me retourne une erreur de syntaxe, je vois pas trop comment arriver à extraire ces lignes, comment gérer la sélection à partir de mon opération basique x=4*I-1 par exemple.
- | Alerter
alors vite fait j'ai remarqué mon erreur : j'ai mis un ":" par inadvertance au lieu d'un ";"
Le script tourne maintenant mais il me créé juste un fichier comprenant 777 lignes (donc 4*194+1 lignes) qui sont vierges.
il ne va donc pas chercher dans mon fichier.log les lognes voulues pour les imprimer dans le fichier.txt
je vais tenter 2/3 trucs en attendant des pistes, je vous tiens au courant si je trouve la solution en attendant votre aide.
merci d'avance
Le script tourne maintenant mais il me créé juste un fichier comprenant 777 lignes (donc 4*194+1 lignes) qui sont vierges.
il ne va donc pas chercher dans mon fichier.log les lognes voulues pour les imprimer dans le fichier.txt
je vais tenter 2/3 trucs en attendant des pistes, je vous tiens au courant si je trouve la solution en attendant votre aide.
merci d'avance
- | Alerter
Voici comment j'ouvre un fichier en lecture dans un script :
Tu accèdes à la ligne courante par $BUF. A toi de faire un test sur le numéro de ligne en cours ($i) et éventuellement de traiter ta ligne avec un cut ou autre pour récupérer ce que tu veux.
i=0
for BUF in `cat $FICHIER`
do
if [condition] then action fi
i=$i+1
done
Tu accèdes à la ligne courante par $BUF. A toi de faire un test sur le numéro de ligne en cours ($i) et éventuellement de traiter ta ligne avec un cut ou autre pour récupérer ce que tu veux.
- | Alerter
Merci pour cette piste, j'ai essayé de l'adapter ainsi mais j'ai toujours une erreur :
l'erreur retournée est : Erreur de syntaxe près du symbole inattendu « x=($i+1)/4 »
j'ai essayé de rajouter un ";" comme sous Matlab mais ça n'a rien changé, une idée sur ce que j'ai raté ?
i=1
for BUF in `cat $erreqw1978.log`
x=($i+1)/4
do
if let $x 2>/dev/null then print $BUF > eqw1978.txt fi
i=$i+1
done
l'erreur retournée est : Erreur de syntaxe près du symbole inattendu « x=($i+1)/4 »
j'ai essayé de rajouter un ";" comme sous Matlab mais ça n'a rien changé, une idée sur ce que j'ai raté ?
- | Alerter
- | Alerter
mykhi a dit :
inverse ligne 3 et ligne 4 ... Le do doit forcément se trouver après le for.Pour être plus propre créé une constante FICHIER (par exemple) et donne lui comme valeur le nom de ton fichier à analyser (et chemin complet si il n'est pas dans le répertoire du script)
ok merci, je viens de tenter ça donc :
FICHIER='erreqw1978.log'
i=1
x=($i+1)/4
for BUF in `cat $FICHIER`
do
if let $x 2>/dev/null then print $BUF > eqw1978.txt fi
i=$i+1
done
mais ça me renvoie toujours l'erreur, cette fois ci pour le "done" : Erreur de syntaxe près du symbole inattendu « done »
j'ai zappé un signe ?
PS : je viens de capter mais si je vire mon expression de x de la boucle ça va pas marcher ? il faut que je le mette dans la boucle for non si je veux qu'il évolue en fonction de i et pouvoir ainsi sélectionner les lignes ?
- | Alerter
Si tu fais ce que tu as mis, x va prendre sa valeur une fois ((1+1)/4 en l'occurrence) et ne bougera plus. Je te conseille quelque chose du genre :
Tant que tu ne rentres pas dans la structure du if, tu peux effectuer autant de commandes que tu le souhaites.
FICHIER='erreqw1978.log'
i=1
for BUF in `cat $FICHIER`
do
x=($i+1)/4
if let $x 2>/dev/null
then
print $BUF > eqw1978.txt
fi
i=$i+1
done
Tant que tu ne rentres pas dans la structure du if, tu peux effectuer autant de commandes que tu le souhaites.
- | Alerter
ok merci ! j'avais retenté en mettant l'expression mais après le do mais ça me retournait aussi la même erreur.
j'ai testé ce que tu m'as dit, ça a l'air de bien parcourir mon fichier mais ça fait des erreurs, voici un extrait de ce que ça me retourne :
apparemment si je comprends bien ça considère mes données comme des fichiers ?
merci de ton aide jusqu'à présent en tout cas
j'ai testé ce que tu m'as dit, ça a l'air de bien parcourir mon fichier mais ça fait des erreurs, voici un extrait de ce que ça me retourne :
....
Error: no such file "11:51"
Warning: unknown mime-type for "[sc_F02D002_910276278_atm_clean_dopcor.fits[*,1]]:" -- using "application/octet-stream"
Error: no such file "[sc_F02D002_910276278_atm_clean_dopcor.fits[*,1]]:"
Error: no such file "1976.975"
Error: no such file "4.219E-18"
Error: no such file "-9.05E-19"
Error: no such file "0.2145"
Error: no such file "-4.24E-19"
Error: no such file "2.005"
Warning: unknown mime-type for "0." -- using "application/octet-stream"
Error: no such file "0."
Warning: unknown mime-type for "(" -- using "application/octet-stream"
Error: no such file "("
Error: no such file "1.2548)"
Warning: unknown mime-type for "(" -- using "application/octet-stream"
Error: no such file "("
Warning: unknown mime-type for ")" -- using "application/octet-stream"
Error: no such file ")"
Error: no such file "(1.1E-18)"
Warning: unknown mime-type for "(" -- using "application/octet-stream"
Error: no such file "("
....
apparemment si je comprends bien ça considère mes données comme des fichiers ?
merci de ton aide jusqu'à présent en tout cas
- | Alerter
Meilleure solution
- | Alerter
Rhooooolala.
Bon, d'abord, savoir si on veut une soluce en awk ou en shell.
Ensuite, si en awk on fait des trucs à la fin (END), on ne le fait qu'une fois, à la fin![[:spamafote] [:spamafote]]()
Re-étude :
En Bourne shell (bsh), c'est Ok. Mais depuis, il y a eu le Korn (ksh) puis le Bourne Again (bash). Alors on n'utilise plus la syntaxe anti-quotes `commande` mais la syntaxe dollar-parenthèses $( commande ). Le gros intérêt, en plus de vivre avec son temps, c'est que la syntaxe dollar-parenthèses est imbricable.
JP, respecte la syntaxe des commandes. Quand mykhi passe une ligne, fais-en autant, ou utilise un point-virgule :
Bon, d'abord, savoir si on veut une soluce en awk ou en shell.
Ensuite, si en awk on fait des trucs à la fin (END), on ne le fait qu'une fois, à la fin
![[:spamafote] [:spamafote]](http://m.bestofmedia.com/sfp/design/usr/fr/smilies/3e/46/spamafote.gif)
Re-étude :
BEGIN {I=1; J=0}
{print > "fichier_n"I".txt" ; J++ ; if (J%4==0) I++ }
Que c'est pas beau !
for BUF in `cat $FICHIER`
En Bourne shell (bsh), c'est Ok. Mais depuis, il y a eu le Korn (ksh) puis le Bourne Again (bash). Alors on n'utilise plus la syntaxe anti-quotes `commande` mais la syntaxe dollar-parenthèses $( commande ). Le gros intérêt, en plus de vivre avec son temps, c'est que la syntaxe dollar-parenthèses est imbricable.
Si le fichier contient des lignes avec espaces, ça ne marche plus. Voici une astuce pour prendre toute la ligne :
for BUF in $( cat $FICHIER )
cat $FILE |
while read LINE ; do
echo "$LINE
done
JP, respecte la syntaxe des commandes. Quand mykhi passe une ligne, fais-en autant, ou utilise un point-virgule :
# // bon
if ..
then
...
fi
while ..
do
...
done
# // pas bon
if .. then
...
fi
while .. do
...
done
# // bon
if .. ; then ... ; fi
while .. ; do ... ; done
- | Alerter
- | Alerter
- | Alerter
- | Alerter
- | Alerter
Merci beaucoup à vous deux pour vos conseils !
pour la syntaxe effectivement je n'avais pas respecté les changements de ligne, etc... il faut que j'apprenne mieux ce langage.
j'ai testé ta version en 2 lignes mykhi et ça a bien marché (j'attends un peu que la discussion soit terminée avant de choisir la meilleure réponse mais je pense que je prendrai la tienne mykhi).
Par contre vu que je débute c'est un peu une boite noire pour moi, pourriez-vous m'aider à comprendre la première partie de cette ligne de commande ?
que veulent dire donc le %, NR, et pourquoi le ==0, de même le print $0 ?
ça m'aiderait à comprendre pour pouvoir l'adapter ensuite et choisir à partir de quelle ligne je veux que ça me prenne une ligne sur 4 ou pour d'autres situations.
merci d'avance
pour la syntaxe effectivement je n'avais pas respecté les changements de ligne, etc... il faut que j'apprenne mieux ce langage.
j'ai testé ta version en 2 lignes mykhi et ça a bien marché (j'attends un peu que la discussion soit terminée avant de choisir la meilleure réponse mais je pense que je prendrai la tienne mykhi).
Par contre vu que je débute c'est un peu une boite noire pour moi, pourriez-vous m'aider à comprendre la première partie de cette ligne de commande ?
awk 'NR%4==0{print $0}' $FICHIER > fichiertest.txt
que veulent dire donc le %, NR, et pourquoi le ==0, de même le print $0 ?
ça m'aiderait à comprendre pour pouvoir l'adapter ensuite et choisir à partir de quelle ligne je veux que ça me prenne une ligne sur 4 ou pour d'autres situations.
merci d'avance
- | Alerter
- | Alerter
- | Alerter
- | Alerter
- | Alerter
Rhoooo !
JPetrucci, quand je te propose d'étudier tel bout de code, j'entends que tu fasses l'effort de chercher toi-même, de tester, de lire la doc, etc. Si tu te contentes de poser la question icic, tu n'avanceras pas, ou très lentement. Et tu reviendras poser les mêmes questions. C'est dommage.
Sauf que ça fera des topics en plus, des pages vues, de la pub vue. Bref, BOM ne t'en voudra pas.
En parlant de faire un effort, tu veux bien mettre des balises [code] là ou tu as écris
JPetrucci, quand je te propose d'étudier tel bout de code, j'entends que tu fasses l'effort de chercher toi-même, de tester, de lire la doc, etc. Si tu te contentes de poser la question icic, tu n'avanceras pas, ou très lentement. Et tu reviendras poser les mêmes questions. C'est dommage.
Sauf que ça fera des topics en plus, des pages vues, de la pub vue. Bref, BOM ne t'en voudra pas.
En parlant de faire un effort, tu veux bien mettre des balises [code] là ou tu as écris
Citation :
dans ton premier message. C'est juste pour faire joli.- | Alerter
Salut Zeb, concernant le bout de code que tu m'avais filé au début je l'ai regardé oui et j'ai essayé de comprendre comment il fonctionnait, peut-être pas aussi en profondeur que tu l'aurais voulu mais c'est vrai qu'en même temps "étudier" me paraissait vague et je ne voyais pas où vraiment tu voulais en venir, mais ça m'a quand même permis de comprendre que j'avais fait une erreur dans mon script initial au moins en oubliant de mettre des entrées dans les BEGIN et END, etc...
Après la doc bien évidemment je la lis mais quand tu as des pages de docs et que tu as des tas de petites fonctions comme awk, grep, etc.... c'est pas forcément évident de se contenter de la doc pour avancer, sur des docs aussi fournies on passe toujours à côté de choses on des fois on en interprète mal d'autres.
Puis si je ne faisais pas l'effort de chercher moi-même je n'aurais pas demandé plus de détails sur la construction des lignes qu'on m'a proposé ici, je me serais contenté de recopier bêtement sans comprendre, non ?
c'est justement en lisant les docs et les forums que j'ai pu tenter mon script initial, et c'est parce que je suis passé à côté de choses que j'ai posé ma question ici, pour en apprendre plus sur ce que j'utilisais mal
Après la doc bien évidemment je la lis mais quand tu as des pages de docs et que tu as des tas de petites fonctions comme awk, grep, etc.... c'est pas forcément évident de se contenter de la doc pour avancer, sur des docs aussi fournies on passe toujours à côté de choses on des fois on en interprète mal d'autres.
Puis si je ne faisais pas l'effort de chercher moi-même je n'aurais pas demandé plus de détails sur la construction des lignes qu'on m'a proposé ici, je me serais contenté de recopier bêtement sans comprendre, non ?
c'est justement en lisant les docs et les forums que j'ai pu tenter mon script initial, et c'est parce que je suis passé à côté de choses que j'ai posé ma question ici, pour en apprendre plus sur ce que j'utilisais mal
- | Alerter
C'est juste.
Tiens, j'ai fait un tuto de bonnes pratiques pour les utilisateurs du shell : http://www.presence-pc.com/forum/ppc/LeMondedeLinux/tut...
Il y a tant de petites commandes sous UNIX ! Mais c'est son grand avantage.
Les commandes à connaître : cat, grep, tail, head.
Celles à bien étudier : sed, awk.
Pour les autres commandes, il faut savoir à peu près à quoi elle servent et se référer à la manpage page au coup par coup.
A savoir que la commande awk est un véritable langage de programmation. Savoir bien l'utiliser est un avantage qui justifie qu'on se penche sur son étude. Certains ne s'embarrassent pas, et plutôt que d'utiliser le shell, préfère directement tout faire en perl.
Tiens, j'ai fait un tuto de bonnes pratiques pour les utilisateurs du shell : http://www.presence-pc.com/forum/ppc/LeMondedeLinux/tut...
Il y a tant de petites commandes sous UNIX ! Mais c'est son grand avantage.
Les commandes à connaître : cat, grep, tail, head.
Celles à bien étudier : sed, awk.
Pour les autres commandes, il faut savoir à peu près à quoi elle servent et se référer à la manpage page au coup par coup.
A savoir que la commande awk est un véritable langage de programmation. Savoir bien l'utiliser est un avantage qui justifie qu'on se penche sur son étude. Certains ne s'embarrassent pas, et plutôt que d'utiliser le shell, préfère directement tout faire en perl.
- | Alerter
Lassé par la pub ? Créez un compte
![[:zeb:3] [:zeb:3]](http://m.bestofmedia.com/sfp/design/usr/fr/smilies/07/fc/zeb:3.gif)
A la base c'est une bonne idée quand même