Forum Programmation.shell Options boucle FOR

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
27
jan.
2016

Bonjour,

Voici un petit script qui doit mettre de la couleur sur les lignes qui contiennent le mot recherché.
La commande "incvisu -t 200" donne les 200 derniers incidents.
Chaque incident est donné sur une ligne et comprends plusieurs arguments, par exemple:
date code error blabla
date code error blabla
date code error blabla
Le but de ce script n'est pas de juste filtrer mais de garder les autres incidents visibles pour voir le contexte, si un autre incident n'est pas à l'origine de celui recherché !
La fonction "Colorize" fonctionne nickel.
Petit problème:
La variable $Line renvoie chaque mot et non chaque ligne, je me retrouve avec une liste de mots, comme ceci:
date
code
error
blabla
or je voudrait que $Line me renvoie chaque ligne comme ceci pour colorer toute la ligne cherchée:
date code error blabla
il doit bien exister un paramètre de FOR pour préciser qu'on veut retourner chaque ligne ?
je suis preneur de toute aide, merci à vous ;)

        #!/bin/sh

        Colorize () {
           if [[ "$1" = *"$Exclud"* ]]; then
              echo -e "\033[41m$1\033[0m"
           else
              echo -e "$1"
           fi
           }

        echo "Entrez un mot clé ou le numéro d'incident:"
        read Exclud

        for Line in `incvisu -t 200`; do
           Colorize "$Line"
           done
  • # Pas sûr de comprendre ton problème..

    Posté par  . Évalué à 2.

    Tu dis que $Line te renvoie chaque mot mais $Line dépend essentiellement de ta commande incvisu.
    Soit c'est incvisu qui ne renvoit pas la ligne comme attendu, soit tu reçois bien la ligne mais tu l'affiches mal.

    As-tu essayer $* à la place de $1 dans tes commandes echo ?

    Sinon grep --color peut être utile aussi :-)

    • [^] # Re: Pas sûr de comprendre ton problème..

      Posté par  . Évalué à 2.

      Sans en savoir plus sur ce que renvoie incvisu, je ne suis pas sûr d'avoir cerné le problème non plus. Mais en l'état, je ne suis pas surpris des retours à la ligne, qui sont ajoutés par echo. L'option '-n' de echo pourrait déjà être un début de piste.

  • # problème d'IFS

    Posté par  (site web personnel) . Évalué à 2.

    Dans une boucle FOR en bash par défaut Line va prendre un par un les paramètres séparés par un espace renvoyés par ta commande.
    Ce comportement est réglé par la variable IFS.
    En initialisant IFS avec autre chose ("\n" par exemple ?), tu devrais obtenir le comportement souhaité.

    Voir ici pour des explications plus complètes.

    Et juste une remarque, la syntaxe $(commande) est à préférer à la syntaxe `commande

    voir la note ici

  • # while et sed

    Posté par  . Évalué à 3.

    #!/bin/sh
    
    echo -n "motif recherche ? "
    read Exclud
    
    while read DATE CODE ERROR BLA
    do
      if [ $DATE = *"$Exclud"* ]
      then
        DATE="\033[41m$DATE\033[0m"
      fi
    
      if [ $CODE = *"$Exclud"* ]
      then
        CODE="\033[41m$CODE\033[0m"
      fi
    
      if [ $ERROR = *"$Exclud"* ]
      then
        ERROR="\033[41m$ERROR\033[0m"
      fi
    
      if [ $BLA = *"$Exclud"* ]
      then
       BLA="\033[41m$BLA\033[0m"
      fi
    
    echo $DATE $CODE $ERROR $BLA
    done <$1

    $1 est le fichier passé en argument lors de l'appel du script lescript.sh lefichier
    $DATE,$CODE, $ERROR seront les 3 premiers elements recupérés par while
    $BLA sera les suivants

    si le separateur est different de l'espace il faudra alors modifier l'IFS avant de lancer le while

    • [^] # Re: while et sed

      Posté par  . Évalué à 2.

      la reponse precedente etait avec while en considerant que tu stocke le resultat de incvisu -t 200 dans un fichier, puis que tu lances le script sur le fichier precedemment créé.

      un truc similaire avec sed qui devrait faire l'affaire et fonctionner en ligne
      par contre je n'ai pas d'ecran couleur sur mon terminal, il faudra tester.

      incvisu -t 200 | sed -e 's/$MOTIF/\033[41m$MOTIF\033[0m/g'

  • # Merci ;)

    Posté par  . Évalué à 2. Dernière modification le 27 janvier 2016 à 13:49.

    Merci à vous tous ^

    c'est résolu avec IFS, c'est exactement ce que je cherchais !!!

            #!/bin/sh
    
            Colorize () {
               if [[ "$1" = *"$Exclud"* ]]; then
                  echo -e "\033[41m$1\033[0m"
               else
                  echo -e "$1"
               fi
               }
    
            old_IFS=$IFS
            IFS=$'\n'
            echo -n "Entrez un mot clé ou le numéro d'incident:"
            read Exclud
    
            for Line in `incvisu -t 200`; do
               Colorize "$Line"
               done
            IFS=$old_IFS
    • [^] # Re: Merci ;)

      Posté par  . Évalué à 2.

      avec ca tu colorises toute la ligne ;)

    • [^] # Re: Merci ;)

      Posté par  . Évalué à 1.

      juste une petite remarque en passant. Ça (les doubles crochets) :

      if [[ "$1" = *"$Exclud"* ]]; then

      c'est une syntaxe Bash ; or ton shebang appelle /bin/sh. Pour ne pas laisser passer ce genre de choses, checkbashisms.pl aide bien (c'est dans un paquet appelé devscripts sous Debian).

    • [^] # Re: Merci ;)

      Posté par  . Évalué à 1.

      Perso je prefere cette syntaxe, plus lisible et pas besoin de bricoler l'IFS:

          incvisu -t 200 | while read Line; do
            Colorize "$Line"
          done
      
      • [^] # Re: Merci ;)

        Posté par  . Évalué à 1.

        Bon alors, dielo j'ai testé ta syntaxe qui me plait vraiment beaucoup, par contre je rencontre un souci que je ne peux pas expliquer, j'ai placé un compteur du nombre d'incisents trouvé avec la recherche comme ceci:
        ```
        #!/bin/sh

        Colorize () {
           if [[ "$1" = *"$Exclud"* ]]; then
              echo -e "\033[41m$1\033[0m"
              NbIncid=$(($NbIncid + 1))
           else
              echo -e "$1"
           fi
           }
        
        clear
        
        echo -n "Entrez un mot clé ou le numéro d'incident: "; read Exclud
        echo -n "Entrez le nombre d'incident à lister: "; read NbVal
        
        NbIncid=0
        
        incvisu -t $NbVal | while read Line; do
           Colorize "$Line"
           done
        
        echo -e " \n$NbIncid incident(s) trouvé(s) correspondant(s)\n "
        

        ```Mais le compteur ne s'incrémente pas il reste à 0, alors que le reste fonctionne bien, la couleur se place bien sur les bonnes lignes, donc il devrait prendre aussi le compteur … mystère !!!

        Par contre avec l'ancienne syntaxe ça fonctionne nickel:
        ```
        #!/bin/sh

        Colorize () {
           if [[ "$1" = *"$Exclud"* ]]; then
              echo -e "\033[41m$1\033[0m"
              NbIncid=$(($NbIncid + 1))
           else
              echo -e "$1"
           fi
           }
        
        clear
        
        echo -n "Entrez un mot clé ou le numéro d'incident: "; read Exclud
        echo -n "Entrez le nombre d'incident à lister: "; read NbVal
        
        NbIncid=0
        
        old_IFS=$IFS; IFS=$'\n'
        for Line in `incvisu -t $NbVal`; do
           Colorize "$Line"
           done
        IFS=$old_IFS
        echo -e " \n$NbIncid incident(s) trouvé(s) correspondant(s)\n "
        

        ```Là je sèche, je ne vois pas pourquoi ça ne marche pas …

        • [^] # Re: Merci ;)

          Posté par  . Évalué à 1.

          Là je sèche, je ne vois pas pourquoi ça ne marche pas

          Vraisemblablement à cause du fork. Tu crées un processus fils dans lequel NbIncid est bien incrémenté (ça se vérifie avec un set -x), sauf que cette variable NbIncid n'est pas le NbIncid du processus père, qui lui reste indéfiniment fixé à la valeur initiale qui tu lui assignes (0). Sous réserve que je ne dise pas de bêtises :)

          Pour t'en sortir, je te suggère d'utiliser un tube nommé :

          #!/bin/bash
          set -e 
          
          Colorize () {
             if [[ "$1" = *"$Exclud"* ]]; then
                echo -e "\033[41m$1\033[0m"
                NbIncid=$(($NbIncid + 1))
             else
                echo -e "$1"
             fi
             }
          
          clear
          
          echo -n "Entrez un mot clé ou le numéro d'incident: "; read Exclud
          echo -n "Entrez le nombre d'incident à lister: "; read NbVal
          
          NbIncid=0
          
          [ -p pipe_for_incvisu ] || mkfifo pipe_for_incvisu
          
          incvisu -t $NbVal > pipe_for_incvisu &
          
          while read Line; do
             Colorize "$Line"
          done < pipe_for_incvisu
          
          echo -e " \n$NbIncid incident(s) trouvé(s) correspondant(s)\n "
          
          rm -f pipe_for_incvisu

          Ça, ça devrait incrémenter correctement ton compteur.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.