IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Awk dans awk


Sujet :

Shell et commandes GNU

  1. #1
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut Awk dans awk
    Bonsoir à tous,

    Dans le cadre de mon administration système et de ma gestion de logs j'aurais besoin d'écrire un algorithme de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Pour chaque ligne de MyFileLog marqué add faire
    ReParcourir MyFileLog jusqu'à voir ligne del
    - Différence entre date add et date del
    FinParcours
    Fpour
    J'ai un fichier de log de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    date heure nom type
    2012-03-26 14:21:03 fichier1 add
    2012-03-26 15:21:03 fichier2 del
    2012-03-26 15:21:03 fichier1 del
    2012-03-26 14:21:03 fichier3 add

    Donc j'avais pensé faire un awk de awk comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    awk '
    {
    awk '
    {
    #Différence entre deux dates
    }
    ' MyFileLog 
    }
    ' MyFileLog

    Mais je crains que cela ne soit pas possible d'une part de faire 2 awk imbriqué et d'ensuite faire partager les variables entres les deux. Je suis à la recherche d'une solution technique viable pour résoudre mon problème. J'ai besoin de votre expertise.

    Merci d'avance de votre réflexion.

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 686
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 686
    Par défaut
    Bonjour,

    dans une seule instance awk, tu utilises un "drapeau" (par défaut, il vaut zéro):
    quand tu rencontres un "add", le drapeau est levé (il vaut un); tu enregistres la date
    quand tu rencontres un "del", si le drapeau est levé, alors le drapeau est baissé (il vaut zéro); tu effectues le calcul.

    ?
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut
    Coucou oui c'est pas mal ce que tu dis mais le problème vient du fait que je dois enregistrer la différence entre plusieurs lignes et là je bloque. Le flag à lui seul ne peut suffire que pour une seule ligne. Comment tu fais avec plusieurs et qui peuvent se répéter qui plus est ?


    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    date heure nom type
    2012-03-26 14:21:03 fichier1 add
    2012-03-26 15:21:03 fichier2 del
    2012-03-26 16:21:03 fichier1 del
    2012-03-26 17:21:03 fichier3 add
    2012-03-26 18:21:03 fichier1 add
    2012-03-26 19:21:03 fichier2 add
    2012-03-26 20:21:03 fichier1 del
    2012-03-26 21:21:03 fichier3 del
    Et je dois pouvoir calculer la différence entre la 1ere date du fichier1 add et la seconde du fichier1 del et ainsi de suite.

    Je dois obtenir ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    fichier1 : Utilisation X Heures
    fichier2 : Utilisation X Heures
    fichier3 : Utilisation X Heures

    Mais il faudrait faire une double boucle et le flag ne suffirai pas il me semble. Et on ne peut pas faire de double awk... C'est pas évident c'est pour cela que j'en appel à vos compétences.

  4. #4
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 686
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 686
    Par défaut
    tu peux utiliser des tableaux associatifs. par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tableau[nomFichier"_flag"] = 0 # ou 1
    tableau[nomFichier] += différence_date
    etc
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut
    Bonjour à tous,

    La solution de Bah marcherait presque avec les tableaux associatifs mais j'ai un problème au niveau d'une condition if dans mon awk. j'ai écris ceci à l'intérieur de mon AWK:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if((tab[$3"_flag"]!=0) || (tab[$3"_flag"]!=1)) {
    tab[$3"_flag"] = -1;
    }
    Quand j'écris ceci, cela rentre à chaque fois dedans malgré que le flag de chaque nom($3) soit à 1 ou 0...

    Mais quand je fais ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if((tab[$3"_flag"]!=0)) {
    tab[$3"_flag"] = -1;
    }
    Cela fonctionne et il ne repasse pas dedans quand il y a des 0. C'est quand j'ajoute une condition ou que j'essaye de faire un else if qu'AWK n'aime plus et fait buguer tout mon programme.

    Vous avez une idée par hasard ?

    merci d'avance

  6. #6
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 686
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 686
    Par défaut
    dans le cas présent, le drapeau vaut 0 ou 1 (exclusivement); il ne doit pas avoir une valeur négative.

    ta première condition dit :
    Code pseudo-code : Sélectionner tout - Visualiser dans une fenêtre à part
    si drapeau ne vaut pas zéro, ou drapeau ne vaut pas un
    or, il doit avoir obligatoirement l'une de ces deux valeurs.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut
    Oui justement c'est ce que je veux avoir... J'essaye d'initialiser tous les flags à -1. De fait si les flags ne valent pas 0 ou 1 je les marques -1 mais quand ils sont marqué 0 ou 1 le programme rentre quand même dans ma condition.

    C'est étrange comme fonctionnement.

    Tu ferais bien comme moi n'est ce pas ? Je ne sais pas s'il y a un ou exclusif ou inclusif dans awk. Mais là n'est pas le problème un || devrait suffire et cela ne fonctionne pas

    En faisant ceci, cela ne fonctionne toujours pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if((tab[$3"_flag"]<0) && (tab[$3"_flag"]>1)) {
    tab[$3"_flag"] = -1;
    }
    Au départ la tab[$3"_flag"] n'existe pas et j'ai besoin de tester si cela existe pour initialiser les valeurs à -1 pour la suite de mon script.

  8. #8
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 686
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 686
    Par défaut
    Tu ferais bien comme moi n'est ce pas ?
    non. Pour moi le drapeau vaut zéro (ou n'existe pas, c'est pareil), ou un. c'est tout.

    en gros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    awk '{if( $1 ~ "fin" && flag == 1 ) flag = 0; if( $1 ~ "debut" ) flag = 1 ; print $1" => flag = "flag}' <<<"a
    b
    c
    fin
    debut
    i
    > o
    > u
    > fin
    f
    g"
    a => flag = 
    b => flag = 
    c => flag = 
    fin => flag = 
    debut => flag = 1
    i => flag = 1
    o => flag = 1
    u => flag = 1
    fin => flag = 0
    f => flag = 0
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut
    Re,

    Alors moi j'ai ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    #!/bin/sh
     
    awk '
    {
    TYPE=$4
     
    printf("%s %s %s %s \n",$1,$2,$3,$4);
     
    if(tab[$3"_flag"]!=0 || tab[$3"_flag"]!=1) {
    tab[$3"_flag"] = -1;
    }
     
    printf("FLAG 1: %s \n",tab[$3"_flag"]);
     
    if(TYPE ~ "add") {
    	tab[$3"_flag"] = 1;
    }
    else if(TYPE ~ "del") {
     
    	if(tab[$3"_flag"]==-1) {
    		printf("DEL SANS ADD %s \n",$3);
    	}
     
    	tab[$3"_flag"] = 0;
    }
     
    printf("FLAG 2: %s \n",tab[$3"_flag"]);
    printf("-----------------------------\n");
     
    }
    END {
     
    }
    ' test
    Avec comme fichier de test ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    2012-10-26 10-20-13 file.d1 add
    2012-10-26 10-20-13 file.d2 del
    2012-10-26 10-20-13 file.d1 del
    2012-10-26 10-20-13 file.d2 add
    2012-10-26 10-20-13 file.d2 del
    2012-10-26 10-20-13 file.d1 add
    2012-10-26 10-20-13 file.d1 del
    Et j'obtiens ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    2012-10-26 10-20-13 file.d1 add 
    FLAG 1: -1 
    FLAG 2: 1 
    -----------------------------
    2012-10-26 10-20-13 file.d2 del 
    FLAG 1: -1 
    DEL SANS ADD file.d2 
    FLAG 2: 0 
    -----------------------------
    2012-10-26 10-20-13 file.d1 del 
    FLAG 1: -1 
    DEL SANS ADD file.d1 
    FLAG 2: 0 
    -----------------------------
    2012-10-26 10-20-13 file.d2 add 
    FLAG 1: -1 
    FLAG 2: 1 
    -----------------------------
    2012-10-26 10-20-13 file.d2 del 
    FLAG 1: -1 
    DEL SANS ADD file.d2 
    FLAG 2: 0 
    -----------------------------
    2012-10-26 10-20-13 file.d1 add 
    FLAG 1: -1 
    FLAG 2: 1 
    -----------------------------
    2012-10-26 10-20-13 file.d1 del 
    FLAG 1: -1 
    DEL SANS ADD file.d1 
    FLAG 2: 0 
    -----------------------------
    Autant dire qu'il y a un problème car il va toujours dans le DEL SANS ADD alors qu'il devrait y aller que pour le premier.

    Qu'est ce que tu en penses ? C'est vraiment étrange.

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 686
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 686
    Par défaut
    Qu'est ce que tu en penses ?
    j'en pense que tu t'obstines à faire en sorte qu'un drapeau puisse valoir -1, alors qu'il ne doit valoir que 0, ou 1 .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    cat akrogames.in
     
    2012-10-26 10-20-13 file.d1 add
    2012-10-26 10-20-13 file.d2 del
    2012-10-26 10-20-13 file.d1 del
    2012-10-26 10-20-13 file.d2 add
    2012-10-26 10-20-13 file.d2 del
    2012-10-26 10-20-13 file.d1 add
    2012-10-26 10-20-13 file.d1 del
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    awk '{
       fic = $3
       if( $4 ~ "del" && flag[fic"_flag"] == 1 ) flag[fic"_flag"] = 0
       if( $4 ~ "add" ) flag[fic"_flag"] = 1
       print $0" => flag["fic"_flag] = "flag[fic"_flag"]
    }' akrogames.in 
      => flag[_flag] = 
    2012-10-26 10-20-13 file.d1 add => flag[file.d1_flag] = 1
    2012-10-26 10-20-13 file.d2 del => flag[file.d2_flag] = 
    2012-10-26 10-20-13 file.d1 del => flag[file.d1_flag] = 0
    2012-10-26 10-20-13 file.d2 add => flag[file.d2_flag] = 1
    2012-10-26 10-20-13 file.d2 del => flag[file.d2_flag] = 0
    2012-10-26 10-20-13 file.d1 add => flag[file.d1_flag] = 1
    2012-10-26 10-20-13 file.d1 del => flag[file.d1_flag] = 0
    ça me paraît bien.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  11. #11
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut
    Mais j'ai besoin d'avoir 3 valeurs dans mon flag car je dois gérer le fait qu'il y a un fichier del alors qu'on ne le voit pas en add. De fait je dois avoir :

    -1 Fichier non marqué
    0 Fichier marqué add
    1 Fichier marqué del

    Et je ne comprends pas pourquoi mes conditions ne fonctionne pas. Cela vient d'AWK ? Je suis paumé.

    Pourquoi cette ligne :
    if(tab[$3"_flag"]!=0 || tab[$3"_flag"]!=1)

    Ne fonctionne pas

    EDIT : D'ailleurs à la ligne 9 le flag n'a pas de valeur mais comment tu fais une condition pour savoir si il y a un flag ou pas ?

    EDIT 2 : Bon je vais me coucher je n'y arrive toujours pas à initialiser mes variables et en plus les conditions ne fonctionne pas. Je poste mon dernier boulot :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    #!/bin/sh
     
    awk '
    {
    FICH=$3;
    TYPE=$4;
     
    printf("%s %s %s %s \n",$1,$2,$3,$4);
    printf("FLAG 1: %s \n",tab[FICH"_flag"]);
    flag = sprintf("%d",tab[FICH"_flag"])
     
    # Initialisation
    if(flag<0 || flag>1) print"INITIALISE";
    else print"OK";
     
     
     
     
    if(TYPE ~ "add") {
    	tab[FICH"_flag"] = 1;
    }
    else if(TYPE ~ "del") {
     
    	if(tab[FICH"_flag"]==0) {
    		#printf("DEL DEJA FAIT ? %s \n",FICH);	
    	}
    	else if(tab[FICH"_flag"]==1) {
    		#printf("DEL AVEC ADD %s \n",FICH);
    	}
    	else {
    		printf("DEL SANS ADD %s \n",FICH);
    	}
     
    	tab[FICH"_flag"] = 0;
    }
     
    printf("FLAG 2: %s \n",tab[FICH"_flag"]);
    printf("-----------------------------\n");
     
    }
    END {
     
    }
    ' test
    Et le résultat désastreux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    2012-10-26 10-20-13 file.d1 add 
    FLAG 1:  
    OK
    FLAG 2: 1 
    -----------------------------
    2012-10-26 10-20-13 file.d2 del 
    FLAG 1:  
    OK
    FLAG 2: 0 
    -----------------------------
    2012-10-26 10-20-13 file.d1 del 
    FLAG 1: 1 
    OK
    FLAG 2: 0 
    -----------------------------
    2012-10-26 10-20-13 file.d2 add 
    FLAG 1: 0 
    OK
    FLAG 2: 1 
    -----------------------------
    2012-10-26 10-20-13 file.d2 del 
    FLAG 1: 1 
    OK
    FLAG 2: 0 
    -----------------------------
    2012-10-26 10-20-13 file.d1 add 
    FLAG 1: 0 
    OK
    FLAG 2: 1 
    -----------------------------
    2012-10-26 10-20-13 file.d1 del 
    FLAG 1: 1 
    OK
    FLAG 2: 0 
    -----------------------------
    Sur les 2 premiers enregistrement cela ne devrait pas afficher OK mais initialise... Voilà... Je me suis tapé toute la doc' sur AWK sans jamais voir un seul test sur des variables. Je ne sais rien faire de plus... SOS ^^

    Mais je suis d'accord avec toi pour ce que tu as fait mais arrives-tu à faire des conditions valables ? Est-ce que mon code fonctionne bien chez toi ? Pour mon algo j'ai besoin d'initialiser les flags car j'ai d'autres traitement derrière mais si je n'arrive même pas à faire déjà çà c'est mal barré. Soit j'initialise le flag au départ, soit je teste si la variable existe et là dans les deux cas je suis bloqué...

    Et apparemment tu ne sais pas non plus car tu n'essayes pas de faire des conditions avec des || ou &&. J'attends ta réponse si jamais il t'est venu une idée durant la nuit.

  12. #12
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 686
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 686
    Par défaut
    on prend les mêmes, et on recommence :
    ~ trois états
    - non-existant
    - levé
    - baissé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    awk '{
     fic = $3
     if( $4 ~ "del" && flag[fic"_flag"] == 1 ) flag[fic"_flag"] = "0"
     if( $4 ~ "add" ) flag[fic"_flag"] = "1"
     if( ! flag[fic"_flag"] ){
        print "le tableau n""\x27""existe pas"
     }else{
        print $0" => flag["fic"_flag] = "flag[fic"_flag"]
     }
    }' akrogames.in 
    le tableau n'existe pas
    2012-10-26 10-20-13 file.d1 add => flag[file.d1_flag] = 1
    le tableau n'existe pas
    2012-10-26 10-20-13 file.d1 del => flag[file.d1_flag] = 0
    2012-10-26 10-20-13 file.d2 add => flag[file.d2_flag] = 1
    2012-10-26 10-20-13 file.d2 del => flag[file.d2_flag] = 0
    2012-10-26 10-20-13 file.d1 add => flag[file.d1_flag] = 1
    2012-10-26 10-20-13 file.d1 del => flag[file.d1_flag] = 0
    ça marche mieux en mettant les valeurs entre guillemets, sinon awk semble ne pas "voir" le zéro.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  13. #13
    Membre très actif

    Inscrit en
    Août 2005
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 401
    Par défaut
    Mister Bah ! Je te remercie pour ton aide.

    La condition qui m'a sauvé : if( ! flag[fic"_flag"] )

    Mais c'est vrai que quand on veut commencer à faire des conditions complexes AWK perd pied et retourne n'importe quoi.

    Je sujet est résolu, c'était pas évident mais j'arrive à initialiser mes valeurs et tout se passe pour le mieux désormais.

    Encore merci pour ta patience et ton aide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Shell] awk dans une boucle while
    Par Shiva dans le forum Linux
    Réponses: 4
    Dernier message: 22/07/2007, 17h28
  2. commande awk dans script perl
    Par sorilazer dans le forum Langage
    Réponses: 3
    Dernier message: 19/07/2007, 11h16
  3. Fonction dans awk
    Par ech363 dans le forum Linux
    Réponses: 5
    Dernier message: 04/12/2006, 18h36
  4. Cut dans Awk
    Par lili_bzh dans le forum Linux
    Réponses: 3
    Dernier message: 24/01/2006, 11h12
  5. Commange Grep dans Awk
    Par lili_bzh dans le forum Linux
    Réponses: 1
    Dernier message: 10/01/2006, 12h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo