Partage
  • Partager sur Facebook
  • Partager sur Twitter

Bash Variable incrémentable non enregistrer

    9 septembre 2019 à 16:34:15

    Bonjour,

    j'ai un petit soucis pour un exercice en bash.

    j'essaye de compter le nombre de mot qui contienne une lettre dans une fonction countMotWithLetter()

    function countMotWithLetter(){
    	i=0
    
    	cat $2 | head | while read ligne
    	do
    		l=$(echo $ligne | grep $1)
    
    		if [ -n $l ]
    		then
    			i=$(($i+1))
    			echo $i
    		else
    			echo "nope"
    		fi
    	done
    
    	echo $i
    }

    mes paramètres sont :

    $1 ='A'

    $2 = dico.txt (une librairie de mot écrit en MAJ)

    je ne comprend pas pourquoi mon echo $i final me donne toujours 0 ... alors que le echo de $i après l'incrémentation dans la boucle me donne 10
    quelqu'un pourrai m'expliquer ? et comment le résoudre ?

    • Partager sur Facebook
    • Partager sur Twitter
      9 septembre 2019 à 17:08:37

      Les variables dans un sous process (pipe ici) ne modifie pas les variables du process parent. Mais celles du parent sont transmissent à sous process.

      Plusieurs solutions:

      • Afficher le résultat final pour le récupérer, éventuellement en passant par d'autre file descripter que stdout/stderr.
      • Utiliser des co-processes, qui sont plus pratiques
      • Ne pas mettre la boucle dans un sous process
        while read line l ; ... ; done <<<$(head "$1")
        Mais on perd l'aspect lecture par flux (ce qui n'est pas dérangeant ici).
      • Partager sur Facebook
      • Partager sur Twitter
        9 septembre 2019 à 18:51:54

        gloups.

        pas glop!

        while read; do...; done < <(command)

        @EclairCat: function et () sont redondant, c'est l'un ou l'autre; function n'est d'ailleurs pas POSIX.
        et, il faut toujours mettre les variables entre guillemets, surtout dans un test.

        • Partager sur Facebook
        • Partager sur Twitter

        Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

          11 septembre 2019 à 1:56:39

          EclairCat a écrit:

          Bonjour,

          j'ai un petit soucis pour un exercice en bash.

          j'essaye de compter le nombre de mot qui contienne une lettre dans une fonction countMotWithLetter()

          function countMotWithLetter(){
          	i=0
          
          	cat $2 | head | while read ligne
          	do
          		l=$(echo $ligne | grep $1)
          
          		if [ -n $l ]
          		then
          			i=$(($i+1))
          			echo $i
          		else
          			echo "nope"
          		fi
          	done
          
          	echo $i
          }

          mes paramètres sont :

          $1 ='A'

          $2 = dico.txt (une librairie de mot écrit en MAJ)

          je ne comprend pas pourquoi mon echo $i final me donne toujours 0 ... alors que le echo de $i après l'incrémentation dans la boucle me donne 10
          quelqu'un pourrai m'expliquer ? et comment le résoudre ?


          Si tu ne fais pas un " typeset -i i=0 ", " i " peut être interprété comme étant une variable contenant du texte.

          man bash
          /typeset

          typeset [-aAfFgilnrtux] [-p] [name[=value] ...]

          " i " contient la chaine " 0 "... et je ne sais pas comment va être interprété l'expression " i=$(($i+1)) "...

          Un simple

          set -x

          avant la fonction te permettra de mieux comprendre...
          Bien à toi.

          -
          Edité par BugHunt3r 11 septembre 2019 à 2:02:44

          • Partager sur Facebook
          • Partager sur Twitter

          Pensez a mettre +1 aux messages qui vous ont aidé et mettre résolu quand cela l'est.

            11 septembre 2019 à 3:37:13

            Si tu ne fais pas un " typeset -i i=0 ", " i " peut être interprété comme étant une variable contenant du texte.

            hmmm. pas tout à fait :

            $ help typeset                             
            [...]                                                                   
                Un synonyme de « déclare ».  Consultez « help declare ».
            $ help declare
            [...]
             -i        pour assigner l'attribut « integer » aux NOMs

            une variable déclarée avec l'attribut integer (nombre) ne peut plus contenir de texte.
            j'entends par texte une chaîne alphanumérique (i.e. des lettres ET éventuellement des chiffres).

            $ decalre -i integer
            $ integer="ga bu zo meu"
            $ echo $integer
            0

            on le voit, toute valeur autre que numérique est ramenée à zéro.

            -
            Edité par dantonq 11 septembre 2019 à 3:37:57

            • Partager sur Facebook
            • Partager sur Twitter

            Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

              11 septembre 2019 à 13:13:40

              @jo_link_noir a raison,

              Ta variable "i" n'est pas exportée : les processus fils ne changeront pas la valeur utilisée par le père... toujours à zéro.
              Comme dans le cours, je te conseille de faire
              let "i = 0"

              et à la place de "i=$(($i+1))" il est possible de faire

              let "i += 1"

              A toi ce choisir la syntaxe qui te convient le mieux.

              J'espère avoir répondu à ta question.
              Bien à toi.

              -
              Edité par BugHunt3r 11 septembre 2019 à 13:17:11

              • Partager sur Facebook
              • Partager sur Twitter

              Pensez a mettre +1 aux messages qui vous ont aidé et mettre résolu quand cela l'est.

                11 septembre 2019 à 15:56:31

                je ferais simplement echo $((i++))ce qui affiche et incrémente i de 1 en 1.
                • Partager sur Facebook
                • Partager sur Twitter

                Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique

                  12 septembre 2019 à 17:25:28

                  Après avoir réfléchi à ton problème, voici ce que cela donne...

                  Le code est perfectible mais celui-ci fonctionne. Comme tu l'as remarqué, tu n'arrives pas à utiliser la valeur en fin de boucle.

                  Pour contourner cet effet de bord (création de processus ne modifiant pas les variables du process père), nous utilisons une syntaxe spéciale en Shell (de la famille Bourne): 

                  { }

                  Si tu utilises ces accolades, un process sera créé pour l'ensemble du traitement et le résultat de celui-ci... donné à la commande qui suit.

                  En gros:

                  mafonction () {
                    {
                      traitement1
                      traitement(s)
                      ...
                    } | command
                  }

                  C'est à dire que tout ce qui sera envoyé sur " stdout " (ou affiché) par les traitements sera pris en entrée de la commande (command) après le "pipe" (|).

                  Maintenant si on prend un peu de recul, une partie du code peut être simplifié et c'est important lorsqu'on écrit un script car le but est de gagner du temps de traitement :)

                  Tous tes tests sont l'équivalent d'un " grep " : recherche d'une chaine (un seul caractère dans ce cas) dans une ligne mais il vaut mieux faire ce traitement sur toutes les lignes en une fois pour gagner du temps.

                  Ta fonction est l'équivalent de :

                  mafonction () {
                    {
                      grep caractère fichier
                    } | wc -l
                  }

                  " grep " cherche le caractère sur chaque ligne du fichier et affiche la ligne contenant le caractère ; " wc -l " compte le nombre d’occurrences (Cf man wc), c.a.d. le nombre de lignes (avec l'option "-l").

                  La commande " grep " étant maintenant seule : le " { } " est superflu et le gain de temps énorme.

                  J'espère que de cette façon, tu comprendras mieux.
                  Bien à toi.

                  -
                  Edité par BugHunt3r 12 septembre 2019 à 17:44:34

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Pensez a mettre +1 aux messages qui vous ont aidé et mettre résolu quand cela l'est.

                  Bash Variable incrémentable non enregistrer

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown