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 POSIX Discussion :

Structure de type Case IF avec awk à plusieurs motifs ?


Sujet :

Shell et commandes POSIX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Consultant MOA
    Inscrit en
    Décembre 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Consultant MOA

    Informations forums :
    Inscription : Décembre 2012
    Messages : 24
    Par défaut Structure de type Case IF avec awk à plusieurs motifs ?
    Bonjour à tous

    Je possède une fichier texte contenant plusieurs mots (pour l'exemple, simplement des lettres)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #fichier_test.txt
    a b c d e f g h i j k l m

    Je cherche a faire des traitement (pour l'exemple, un simple affichage) selon les motifs trouvés.
    A savoir qu'il faut absolument une combinaison de motifs (l'ordre et la case n'ont pas d'importance) d'ou l'utilisation de awk qui permet d'utiliser l'opérateur ET

    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
    #!/bin/bash
    FichierDeTest="fichier_test.txt"
     
    # Je chercher le motif 1 ET le motif 2
    TestPresence_a_b=$(awk '/a/ && /b/' fichier_test.txt)
     
    #Si la variable n'est pas vide (== résultat de awk), la chaine est trouvé
    if [ -n "$TestPresence_a_b" ] ; then
    	echo "La chaine a b est présente"
    fi
     
    # Je chercher le motif 1 ET le motif 2 ET le motif 3
    TestPresence_c_e_f=$(awk '/c/ && /e/ && /f/' fichier_test.txt)
     
    #Si la variable n'est pas vide (== résultat de awk), la chaine est trouvé
    if [ -n "$TestPresence_c_e_f" ] ; then
    	echo "La chaine c e f est présente"
    fi
     
    # etendre à d'autres cas, exemple 
    #g h i
    #l m
    Pour l'exemple, je n'en ait mis que deux, mais je dois en avoir plus.
    Seulement, mon code se répéte déjà donc je cherche à faire quelque chose de plus générique. Je me demande si je peut créer une struture qui ressemble au Case If

    Merci d'avance de vos suggestions.


    Ajout de précisions



    J'apporte quelques précisions à ma demande

    - je recherche bien des motifs qui sont des mots-clés

    - je dois avoir une 50 aine de cas à traiter, qui peuvent avoir certains mots en commun (et non pas la totalité), par exemple a b ; a d e ; c e f; ...
    Je dois donc chercher entre 2 et 4 mots-clés pour chaque cas.

    - quand je trouve une combinaison de mots-clés, je doit renvoyer une sorte de définition donc du texte. On peut considérer que c'est une sorte de dictionnaire avec, en entrée, des mots-clés dont l'ordre importe peu.

    - j'ai d'abord testé par grep avec le | mais le comportement était un OR et pas un AND. Peut-être me suis-je trompé dans la syntaxe ?

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 135
    Par défaut
    Une petite fonction ?
    En entrée le fichier et les motifs cherchés
    En sortie, 0 si tous les motifs sont trouvés, 1 sinon
    Affichage des lignes correspondant au résultat
    Seule contrainte : utilise deux fichiers temporaires
    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
    function  CherchePattern
    { cp "$1" fic_tmp
      # Boucler sur les motifs
      for pattern in "$@"
      do
        if [ -n "$pattern" ]
        then
          # Réduire le fichier de travail aux lignes trouvées
          grep "$pattern" fic_tmp > fic_res
          cp fic_res fic_tmp
        fi
        # Si aucune ligne, inutile de continuer
        [ -s fic_tmp ] && break
      done
      # Récupérer le résultat et l'afficher
      [ -s fic_tmp ] && Rc=1 || Rc=0
      cat fic_tmp
      rm -f fic_tmp fic_res
      return $Rc
    }
    Il y a certainement matière à optimiser
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    effectivement faire une fonction est sans doute une bonne idée, par contre on sait pas si le traitement est identique à chaque fois ou non etc.
    on peut partir sur awk par contre on perd la notation regex && regex ça ne passe pas, en revanche on peut contourner le problème avec la fonction match() au sein d'une boucle :
    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
    #!/bin/bash
     
    function multigrep(){
      fichier="$1"; shift 1
      expression="$@"
      res=$(awk -vu="$expression" '
      BEGIN{
        n = split(u, t, / AND /);    # on crée le tableau t sur la base de lexpression u passée en paramètre
      }
      $0 ~ t[1] {                    # la ligne quon recherche matchera forcement au moins le premier element du tableau
        for(i = 2; i < n+1; i++) {
          if (!match($0, t[i])) {    # si au moins un des autres elements ne match pas cest que la ligne nest pas bonne
            next;
          }
        }
        print                        # sinon on a trouvé une ligne valable et on laffiche
      }' $fichier)
      echo "----------------"
      if [ -n "$res" ]; then
        echo "trouvé (expression = \"$expression\") :"
        echo "$res"
        return 0
      else
        echo "not trouvé (expression = \"$expression\")"
        return 1
      fi
    }
     
    multigrep fichier "alpha"
    multigrep fichier "bravo AND charlie"
    multigrep fichier "foxtrott AND echo AND charlie"
    multigrep fichier "pouet"
    et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ----------------
    trouvé (expression = "alpha") :
    alpha bravo charlie
    echo alpha charlie foxtrott
    alpha
    ----------------
    trouvé (expression = "bravo AND charlie") :
    alpha bravo charlie
    bravo charlie foxtrott
    ----------------
    trouvé (expression = "foxtrott AND echo AND charlie") :
    echo alpha charlie foxtrott
    ----------------
    not trouvé (expression = "pouet")
    nb: la notation choisie machin AND truc est totalement cosmétique
    nb2: c'est une approche pas du tout optimisée, pour chaque expression recherchée on lit l'intégralité du fichier

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

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

    Citation Envoyé par BufferBob
    sur awk par contre on perd la notation regex && regex ça ne passe pas
    comment fais-tu ? ça devrait ne pas poser de problèmes.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    comment fais-tu ? ça devrait ne pas poser de problèmes.
    ben je vois pas trop comment, l'idée ce serait de passer awk -vTOTO="/regex1/ && /regex2/" 'TOTO {action}' fichier, passer une simple regex je dis pas, mais passer une expression complète j'ai pas l'impression qu'on puisse...

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 661
    Par défaut
    BufferBob : vu comme ça, en effet.

    Pour l'exemple, je n'en ait mis que deux, mais je dois en avoir plus.
    il faut détailler ton projet : est-ce fixe ? est-ce variable ? est-ce paramétrable ?...
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    Citation Envoyé par laliemendez Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # Je chercher le motif 1 ET le motif 2
    TestPresence_a_b=$(awk '/a/ && /b/' fichier_test.txt)
    (...)
    # Je chercher le motif 1 ET le motif 2 ET le motif 3
    TestPresence_c_e_f=$(awk '/c/ && /e/ && /f/' fichier_test.txt)
    (...)
    # etendre à d'autres cas, exemple 
    #g h i
    #l m
    moi ça me paraissait assez clair au contraire, il cherche n motifs dans le fichier, c'est pour ça qu'il voulait se reposer sur la syntaxe /regex1/ && /regex2/ && ... /regexn/ de awk, tout le propos étant de passer l'expression de manière dynamique

    si on connait n à l'avance c'est facile effectivement de s'en sortir avec un grep | grep | grep, mais si n est variable on est coincé

  8. #8
    Membre averti
    Femme Profil pro
    Consultant MOA
    Inscrit en
    Décembre 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Consultant MOA

    Informations forums :
    Inscription : Décembre 2012
    Messages : 24
    Par défaut
    Bonjour

    J'apporte quelques précisions à ma demande

    - je recherche bien des motifs qui sont des mots-clés

    - je dois avoir une 50 aine de cas à traiter, qui peuvent avoir certains mots en commun (et non pas la totalité), par exemple a b ; a d e ; c e f; ...
    Je dois donc chercher entre 2 et 4 mots-clés pour chaque cas.

    - quand je trouve une combinaison de mots-clés, je doit renvoyer une sorte de définition donc du texte. On peut considérer que c'est une sorte de dictionnaire avec, en entrée, des mots-clés dont l'ordre importe peu.

    - j'ai d'abord testé par grep avec le | mais le comportement était un OR et pas un AND. Peut-être me suis-je trompé dans la syntaxe ?

  9. #9
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    - quand je trouve une combinaison de mots-clés, je doit renvoyer une sorte de définition donc du texte. On peut considérer que c'est une sorte de dictionnaire avec, en entrée, des mots-clés dont l'ordre importe peu.
    si on a :
    • la ligne "alpha bravo charlie delta echo"
    • le cas n°28 "alpha AND bravo"
    • le cas n°42 "alpha AND bravo AND charlie"
    • le cas n°49 "bravo AND charlie"

    que doit faire le programme, identifier les 3 cas distincts, identifier uniquement le premier cas rencontré (le cas n°28), identifier le cas avec un maximum de motifs trouvés ("alpha AND bravo AND charlie"), autre ?

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 661
    Par défaut
    Gawk possède une structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                  switch (expression) {
                  case value|regex : statement
                  ...
                  [ default: statement ]
                  }
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  11. #11
    Membre averti
    Femme Profil pro
    Consultant MOA
    Inscrit en
    Décembre 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Consultant MOA

    Informations forums :
    Inscription : Décembre 2012
    Messages : 24
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Gawk possède une structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                  switch (expression) {
                  case value|regex : statement
                  ...
                  [ default: statement ]
                  }
    Pas encore eut le temps de tester (les priorités du lundi matin qui changent ... )
    Mais visuellement, cela a l'air de répondre à mon besoin.

    Je testerai et je dirai ce qu'il en est

  12. #12
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 29/03/2014, 23h27
  2. Réponses: 1
    Dernier message: 18/04/2008, 17h16
  3. Probleme avec awk et type de variables
    Par canaboss dans le forum Linux
    Réponses: 6
    Dernier message: 16/04/2008, 20h04
  4. [VB6] Spécifier plusieurs types de fichiers avec FileSearch
    Par yaya54 dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 31/01/2008, 15h59
  5. case/when avec plusieurs valeurs pour le then
    Par Neo41 dans le forum Langage SQL
    Réponses: 7
    Dernier message: 02/09/2005, 15h58

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