Partage
  • Partager sur Facebook
  • Partager sur Twitter

lecture fichier txt avec bash

    2 décembre 2019 à 18:14:03

    Bonsoir, dans le cadre d'un projet en shell je dois réaliser un fichier bash qui puisse lire ce fichier texte ci dessous :

    1:2:3:=somme(l1c1,l1c3)
    
    4:=[l1c4]:7:=moyenne(l2c1,l2c3)
    
    =+(l1c1,size(l3c3)):=shell(expr 12 + 89):/bin/ls:=/(l3c1,l3c2)

    par exemple =somme est une fonction qui devra calculer la somme de 1, 2 et 3

    Il ne faut pas utiliser de tableau, je veux donc ranger chaque élément dans une variable avec 

    while read lig
    do
      while read col
      do
        l1c1=`echo $lig | cut -d: -f1`
        l1c2=`echo $lig | cut -d: -f2`
        l1c3=`echo $lig | cut -d: -f3`
        l1c4=`echo $lig | cut -d: -f4`
    
      done
      l2c1=`echo $lig | cut -d: -f1`
    
    
    done <data.txt
    
    
    echo $l2c1
    
    mais problème, il m'affiche toujours 1 pour $l2c1 or je voudrais qu'il m'affiche 4
    merci beaucoup d'avance pour votre aide :) 

    -
    Edité par MoiMoi204 2 décembre 2019 à 18:25:49

    • Partager sur Facebook
    • Partager sur Twitter
      2 décembre 2019 à 19:49:27

      salut,

      je ne suis pas convaincu de l'utilité de la seconde boucle while.

      si tu veux obtenir la somme de 1 et 3, respectivement l1c1 et l1c3, il faut les additionner.

      • Partager sur Facebook
      • Partager sur Twitter
      « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
        2 décembre 2019 à 19:56:30

        Bonsoir,

        MoiMoi204 a écrit:

        Bonsoir, dans le cadre d'un projet en shell je dois réaliser un fichier bash qui puisse lire ce fichier texte ci dessous :

        MoiMoi204 a écrit:

        par exemple =somme est une fonction qui devra calculer la somme de 1, 2 et 3

        Il ne faut pas utiliser de tableau, je veux donc ranger chaque élément dans une variable avec

        Ton script doit lire? Ou interpréter le fichier?

        MoiMoi204 a écrit:

        mais problème, il m'affiche toujours 1 pour $l2c1 or je voudrais qu'il m'affiche 4

        merci beaucoup d'avance pour votre aide :) 

        Fais:
        bash -x tonscript.sh

        Et essaye de comprendre ce qu'il fait.

        Je n'ai pas compris ce que tu as essayé de faire perso? Pourrais-tu l'expliquer?

        Si tu ne dois pas utiliser de tableau, je doute que c'est pour utiliser des variables avec des noms du type <ligne1colonne1>... Il faut probablement interpréter chaque ligne à la volée.

        -
        Edité par KoaTao 2 décembre 2019 à 20:01:53

        • Partager sur Facebook
        • Partager sur Twitter
          2 décembre 2019 à 20:02:34

          dantonq a écrit:

          salut,

          je ne suis pas convaincu de l'utilité de la seconde boucle while.

          si tu veux obtenir la somme de 1 et 3, respectivement l1c1 et l1c3, il faut les additionner.


          je veux imbriquer deux while parce que je peux n'en faire qu'un mais il me donnera toute la colonne c'est à dire comme pour l'exemple 1 4 =+(l1c1,size(l3c3)) or je les veux séparément

          puis j'ai une suite de fonction telles que somme, moyenne, variance etc; je n'aurai qu'à les appeler

          KoaTao a écrit:

          Bonsoir,

          MoiMoi204 a écrit:

          Bonsoir, dans le cadre d'un projet en shell je dois réaliser un fichier bash qui puisse lire ce fichier texte ci dessous :

          MoiMoi204 a écrit:

          par exemple =somme est une fonction qui devra calculer la somme de 1, 2 et 3

          Il ne faut pas utiliser de tableau, je veux donc ranger chaque élément dans une variable avec

          Ton script doit lire? Ou interpréter le fichier?


          Mon script doit pouvoir remplacer dans le fichier texte, =somme(l1c1,l1c3) doit être remplacer par 6 etc pour chaque fonction

          MoiMoi204 a écrit:

          mais problème, il m'affiche toujours 1 pour $l2c1 or je voudrais qu'il m'affiche 4

          merci beaucoup d'avance pour votre aide :) 


          Fais:

          bash -x tonscript.sh

          Et essaye de comprendre ce qu'il fait.

          Je n'ai pas compris ce que tu as essayé de faire perso? Pourrais-tu l'expliquer?

          Si tu ne dois pas utiliser de tableau, je doute que c'est pour utiliser des variables avec des noms du type <ligne1colonne1>... Il faut probablement interpréter chaque ligne à la volée.

          -
          Edité par KoaTao il y a moins de 30s

          Le problème est la ligne 

          l2c1=`echo $lig | cut -d: -f1`

          j'aimerais retourner à la ligne pour pouvoir mettre 4 dans la variable l2c1 mais il recommence à la 1ère ligne

          pour mieux comprendre mon fichier texte qui est donné comme ceci 

          1:2:3:=somme(l1c1,l1c3)
          4:=[l1c4]:7:=moyenne(l2c1,l2c3)
          =+(l1c1,size(l3c3)):=shell(expr 12 + 89):/bin/ls:=/(l3c1,l3c2)

          doit être transformé comme tel 

          1:2:3:6
          4:6:7:5.66666666666666666666
          67669:101:/bin/ls:669.99009900990099009900

          -
          Edité par MoiMoi204 2 décembre 2019 à 20:12:51

          • Partager sur Facebook
          • Partager sur Twitter
            2 décembre 2019 à 20:17:25

            Tes deux boucles Tant que lisent la même entrée (stdin) je suppose:

            while read ligne1; do
                while read lignesRestantesDuFichier; do
                    echo "Deuxième boucle: $lignesRestantesDuFichier"
                done
                echo "Fin du fichier"
            done < fichier.txt

            Ensuite, sur comment implémenter tous ça pour tout interpréter sans utiliser de tableau... c'est différent. Est-ce que le fichier d'input peut changer? Nb de lignes? Colonnes? C'est très confus pour moi.

            -
            Edité par KoaTao 2 décembre 2019 à 20:25:09

            • Partager sur Facebook
            • Partager sur Twitter
              2 décembre 2019 à 20:46:07

              KoaTao a écrit:

              Tes deux boucles Tant que lisent la même entrée (stdin) je suppose:

              while read ligne1; do
                  while read lignesRestantesDuFichier; do
                      echo "Deuxième boucle: $lignesRestantesDuFichier"
                  done
                  echo "Fin du fichier"
              done < fichier.txt

              Ensuite, sur comment implémenter tous ça pour tout interpréter sans utiliser de tableau... c'est différent. Est-ce que le fichier d'input peut changer? Nb de lignes? Colonnes? C'est très confus pour moi.

              -
              Edité par KoaTao il y a 13 minutes

              comme expliqué plus haut en ayant pour départ 

              1:2:3:=somme(l1c1,l1c3)
              4:=[l1c4]:7:=moyenne(l2c1,l2c3)
              =+(l1c1,size(l3c3)):=shell(expr 12 + 89):/bin/ls:=/(l3c1,l3c2)
              

              je dois avoir 

              1:2:3:6
              4:6:7:5.66666666666666666666
              67669:101:/bin/ls:669.99009900990099009900

              c'est à dire autant d'arguments qu'avant, tous les arguments du départ commençant par = doivent être remplacés par la fonction qui convient



              • Partager sur Facebook
              • Partager sur Twitter
                2 décembre 2019 à 22:34:22

                Bonjour,

                Ça nous explique pas ce que tu veux faire mais bon...

                De ce que je comprend, chaque ligne peut faire appel à des valeurs se trouvant sur les lignes précédentes. Donc il faut d'abord interpréter la ligne 1 et stocker le résultat pour pouvoir y accéder ci besoin, puis la ligne 2 et ainsi de suite.

                Un chose toute simple qu'on peut faire est:

                while read ligne; do
                        ####
                        # Faire l'interprétation ici
                        ####
                        retour+="$resultatInterprétation\n"
                done <data.txt
                echo -e "$retour"

                Il existe fort probablement de meilleures solutions.

                -
                Edité par KoaTao 2 décembre 2019 à 22:37:18

                • Partager sur Facebook
                • Partager sur Twitter
                  2 décembre 2019 à 23:03:50

                  KoaTao a écrit:

                  Bonjour,

                  Ça nous explique pas ce que tu veux faire mais bon...

                  De ce que je comprend, chaque ligne peut faire appel à des valeurs se trouvant sur les lignes précédentes. Donc il faut d'abord interpréter la ligne 1 et stocker le résultat pour pouvoir y accéder ci besoin, puis la ligne 2 et ainsi de suite.

                  Un chose toute simple qu'on peut faire est:

                  while read ligne; do
                          ####
                          # Faire l'interprétation ici
                          ####
                          retour+="$resultatInterprétation\n"
                  done <data.txt
                  echo -e "$retour"

                  Il existe fort probablement de meilleures solutions.

                  -
                  Edité par KoaTao il y a 12 minutes

                  Il faut en effet procéder ligne par ligne comme vous le dites mais je ne sais pas comment faire 

                  j'essaye cette commande basique mais il parcourt encore tout le fichier et non la première ligne uniquement

                  while read ligne
                  do
                    retour+=$ligne
                  done <data.txt
                  echo -e "$retour"
                  





                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 décembre 2019 à 23:26:00

                    Si tu ne comprends pas ce que tu as écrit dans ton premier script (la structure while read line; do #ACTION; done < fichier.input), tu ne pourras pas résoudre cet exercice.

                    A un moment, il faut apprendre les bases de Bash.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 décembre 2019 à 23:49:02

                      c'est pourquoi je demande de l'aide en effet j'arrive à prendre chaque mot avec 

                      while IFS=: read lig1 lig2 lig3 lig4
                      do
                        echo -e "
                        l1c1 : $lig1\n\
                        l1c2 : $lig2\n\
                        l1c3 : $lig3\n\
                        l1c4 : $lig4\n\n"
                      done < data.txt
                      

                      j'obtiens 

                      l1c1 : 1
                      l1c2 : 2
                      l1c3 : 3
                      l1c4 : =somme(l1c1,l1c3)
                      
                      l1c1 : 4
                      l1c2 : 7
                      l1c3 : =[l1c4]
                      l1c4 : =moyenne(l2c1,l2c3)
                      
                      l1c1 : =+(l1c1,size(l3c3))
                      l1c2 : =shell(expr 12 + 89)
                      l1c3 : /bin/ls
                      l1c4 : =/(l3c1,l3c2)
                      
                      

                      or je voudrais pouvoir faire  

                      l1c1 : 1
                      l1c2 : 2
                      l1c3 : 3
                      l1c4 : =somme(l1c1,l1c3)
                      
                      l2c1 : 4
                      l2c2 : 7
                      l2c3 : =[l1c4]
                      l2c4 : =moyenne(l2c1,l2c3)
                      
                      l3c1 : =+(l1c1,size(l3c3))
                      l3c2 : =shell(expr 12 + 89)
                      l3c3 : /bin/ls
                      l3c4 : =/(l3c1,l3c2)

                      pour assigner à chaque ligne et colonne une chaine pour ainsi appeler les fonctions correspondantes


                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 décembre 2019 à 0:46:25

                        Si on simplifie le problème, on a en entrée:

                        1*1:1*2:1*3:1*4
                        2*1:2*2:2*3:2*4
                        ---
                        n*1:n*2:n*3:n*4

                        Qui ressemble fortement à un tableau (probablement la raison pour laquelle l'utilisation de tableau est prohibé).

                        On peut donc identifier chaque champs de chaque ligne. Avec la boucle, on peut aussi lire 4 champs par 4 champs.

                        Si on reste dans un truc tout simple:

                        • on interprète chaque ligne et on place le résultat dans une seule variable qui stockera tous les résultats dans une chaîne de caractère avec un séparateur de champ défini;
                        • Ensuite, lors de l'interprétation, lorsqu'on aura besoin de récupérer la valeur d'un champ d'une ligne précédente, il suffira d'extraire le champ (qu'on sait calculer) correspondant dans notre variable.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 décembre 2019 à 1:09:47

                          je vous remercie pour votre patience, 

                          voici ce que j'ai fait 

                          while read lig
                          do
                              l1c1=`echo $lig | cut -d: -f1`
                              l1c2=`echo $lig | cut -d: -f2`
                              l1c3=`echo $lig | cut -d: -f3`
                              l1c4=`echo $lig | cut -d: -f4`
                          
                              if [ ${l1c4:0:1} = '=' ]; then
                          
                                if [[ $l1c4 =~ "somme" ]]; then
                          
                                  if [[ $l1c4 =~ "l1c1" ]] && [[ $l1c4 =~ "l1c3" ]]; then
                                    somme $l1c1 $l1c2 $l1c3
                                  fi
                          
                                elif [[ $l1c4 =~ "moyenne" ]]; then
                          
                                  if [[ $l1c4 =~ "l1c1" ]] && [[ $l1c4 =~ "l1c3" ]]; then
                                    moyenne $l1c1 $l1c2 $l1c3
                                  fi
                          
                                else
                                  echo ko
                                fi
                              fi
                          
                              echo "$l1c1:$l1c2:$l1c3:$l1c4"
                          
                          done <data.txt
                          

                          comme vous le dites ça fonctionnera pour la première ligne mais si j'essaye avec la deuxième ligne je ne peux plus récupérer les premières valeurs de la première ligne c'est à dire 1 2 et 3

                          • Partager sur Facebook
                          • Partager sur Twitter
                            3 décembre 2019 à 4:21:55

                            « Allez! avec une tenaille, et en vous servant uniquement de votre main faible (la gauche pour les droitiers...), faites une miniature de la Joconde. »

                            :o

                            #!/bin/bash
                            
                            nl=0
                            while read l$((++nl))
                            do
                               lnl=l$nl
                               nc=0
                               while read -d :
                               do
                                  r=l${nl}c$((++nc))
                                  echo ${!r}
                               done <<<${!lnl}:
                               echo
                            done < ./tonFichier

                            les points d'exclamation introduisent une indirection, c'est-à-dire une référence à un nom de variable :

                            $ var=foobar
                            $ nom=var
                            $ echo ${!nom}
                            foobar

                            dans le code précédent, qui lit tonFichier, les noms de variables sont construits en fonction du numéro de ligne (l${nl}) et du numéro de champ (c${nc})

                            bon courage.

                            -
                            Edité par dantonq 3 décembre 2019 à 4:23:08

                            • Partager sur Facebook
                            • Partager sur Twitter
                            « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
                              3 décembre 2019 à 15:29:17

                              donc si je comprends bien votre code, pour l'instant ça n'affiche rien mais si je dois faire des tests c'est donc entre done<<<${!lnl}: 

                              et done< ./tonFichier

                              • Partager sur Facebook
                              • Partager sur Twitter
                                3 décembre 2019 à 15:52:17

                                si, ça affiche quelque chose : il y a des echo, dont un pour séparer les lignes.

                                oui, une fois que les variables sont construites, tu peux faire des tests.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
                                  3 décembre 2019 à 16:00:58

                                  normalement oui le

                                   echo${!r}

                                  mais ça n'affiche que du vide avec le fichier data.txt

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    3 décembre 2019 à 16:18:57

                                    mouais. j'ai oublié de recopier quelques parties du code :
                                    nl=0
                                    while IFS=: read l$((++nl))
                                    do
                                       lnl=l$nl
                                       echo "ligne $nl = ${!lnl}"
                                       nc=0
                                       while read -d : ${lnl}c$((++nc))
                                       do
                                          r=${lnl}c$nc
                                          echo "$r = ${!r}"
                                       done <<<${!lnl}:
                                       echo
                                    done < /tmp/input
                                    ligne 1 = 1:2:3:=somme(l1c1,l1c3)
                                    l1c1 = 1
                                    l1c2 = 2
                                    l1c3 = 3
                                    l1c4 = =somme(l1c1,l1c3)
                                    
                                    ligne 2 = 4:=[l1c4]:7:=moyenne(l2c1,l2c3)
                                    l2c1 = 4
                                    l2c2 = =[l1c4]
                                    l2c3 = 7
                                    l2c4 = =moyenne(l2c1,l2c3)
                                    
                                    ligne 3 = =+(l1c1,size(l3c3)):=shell(expr 12 + 89):/bin/ls:=/(l3c1,l3c2)
                                    l3c1 = =+(l1c1,size(l3c3))
                                    l3c2 = =shell(expr 12 + 89)
                                    l3c3 = /bin/ls
                                    l3c4 = =/(l3c1,l3c2)
                                    
                                    


                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
                                      3 décembre 2019 à 16:27:55

                                      ah bah oui je suis bête j'aurais dû le deviner il ne lisait rien le deuxième while, merci encore une fois je vais essayer avec ça
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        3 décembre 2019 à 17:05:36

                                        si il lisait, mais la lecture était assignée à REPLY, et pas aux variables en cours de construction. :(
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
                                          3 décembre 2019 à 18:26:16

                                          ah oui d'accord je vois,

                                          je pense que j'y suis presque 

                                          voici ma fonction somme 

                                          somme(){
                                            sum=0
                                            for item in $@;
                                            do
                                              sum=$(($sum + $item))
                                            done
                                            echo $sum
                                          }
                                          

                                          et voici mon code 

                                          nl=0
                                          while IFS=: read l$((++nl))
                                          do
                                             lnl=l$nl
                                             #echo "ligne $nl = ${!lnl}"
                                             nc=0
                                             while read -d : ${lnl}c$((++nc))
                                             do
                                                r=${lnl}c$nc
                                                if [[ "$r = ${!r}" =~ "somme" ]]
                                                then
                                                  if [[ "$r = ${!r}" =~ "l1c1" ]] && [[ "$r = ${!r}" =~ "l1c3" ]]
                                                  then
                                                    somme ${lnl}c$1 ${lnl}c$2 ${lnl}c$3 
                                                  fi
                                                fi
                                                #echo "$r = ${!r}"
                                             done <<<${!lnl}:
                                             echo
                                          done < data.txt
                                          



                                          l'erreur se trouve à ligne 
                                          somme ${lnl}c$1 ${lnl}c$2 ${lnl}c$3


                                          j'aimerais en effet calculer la somme du premier nombre de la première ligne ,du deuxième nombre de la première ligne et du troisième de la première ligne ( càd 1,2 et 3 ) 
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            3 décembre 2019 à 18:46:27

                                            je pensais que tu voulais exécuter l'instruit somme(l1c1,l1c3)

                                            que je lis comme la somme du premier et du troisième champs de la première ligne.

                                             comme l'a suggérer KoaTao :

                                            Il faut probablement interpréter chaque ligne à la volée.

                                            donc réutiliser les données du fichiers, et procéder à un autre découpage si un champ contient le nom d'une fonction pour récupérer le nom de la fonction et les données auxquelles elle s'applique.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
                                              3 décembre 2019 à 18:51:54

                                              oui la fonction addition permet d'additionner deux champs, la fonction somme permet de sommer une suite de champs de la même ligne débutant par le champ argument1 et finissant par le champ argument2

                                              ça veut dire que le code que vous m'avez fourni n'est plus adéquat au sujet ?

                                              -
                                              Edité par MoiMoi204 3 décembre 2019 à 18:52:56

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                3 décembre 2019 à 19:36:53

                                                c'est un début, pour te montrer comment construire des variables, et les retrouver.

                                                il reste à faire interpréter les données fournies dans le fichiers.

                                                ça ne doit pas être très différent : le fichier donne des références de nom de variables, il faut faire en sorte (avec une indirection aussi ?) qu'elles affichent les valeurs correctes.

                                                si tu n'y arrives pas, je ferai des tests demain.

                                                --
                                                bonne nuit, à demain. :)

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                « un problème clairement exposé est à moitié résolu. » | je ne réponds pas aux questions techniques par MP.
                                                  3 décembre 2019 à 20:44:11

                                                  merci je vais essayer bonne nuit à vous :D
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    4 décembre 2019 à 11:23:29

                                                    C'est vraiment sadique comme exercice...

                                                    Tu devrais créer une fonction pour parser qui retourne la chaîne de caractère que doit contenir le champs interpréter. Je te conseille de découper au maximum ton programme en tâche simple à réaliser, plutôt que d'essayer de tout faire d'un coup.

                                                    Tu devrais quand même éviter au maximum d'avoir des structures if-then-elif imbriquées, car ça va tuer la lisibilité.

                                                    Tu peux utiliser case déjà: https://bash.cyberciti.biz/guide/The_case_statement.

                                                    #!/usr/bin/env bash
                                                    parsePermierCara(){
                                                      field="$1"
                                                      case "${field:0:1}" in
                                                        "=")
                                                          echo "Affectation"
                                                          #Continuer à parser
                                                          ;;
                                                        *)
                                                          #Rien à faire dans les autres cas
                                                          echo "$field"
                                                          ;;
                                                        esac
                                                    }
                                                    
                                                    nl=0
                                                    while IFS=: read l$((++nl))
                                                    do
                                                       lnl=l$nl
                                                       nc=0
                                                       while read -d : ${lnl}c$((++nc))
                                                       do
                                                          r=${lnl}c$nc
                                                          declare "${r}"=$(parsePermierCara "${!r}")
                                                          echo "${!r}"
                                                       done <<<${!lnl}:
                                                    done < fichier.txt

                                                    Le script n'est bien sur pas complet, mais l'idée est d'interpréter chaque champs en cherchant les caractères ayant une signification spéciale (comme «=», «[» «(» «)» par exemple), et d'afficher le résultat. Ensuite, on assigne ce résultat à la variable correspondant au champ.

                                                    Une fois que tu as réalisé ton «interpréteur», il ne te reste plus qu'à formater la sortie.

                                                    J'utilise

                                                    declare "${r}"=$(parsePermierCara "${!r}")

                                                     Pour assigner une nouvelle valeur au champ interprété.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter

                                                    lecture fichier txt avec bash

                                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                    • Editeur
                                                    • Markdown