Script bash - Récupérer des colonnes

Résolu
Bonjour à tous,

J'ai débarqué sur la planète bash la semaine dernière :)
Je dois classer des données du style donnee_lieu.txt:
12:56:15:000 25/07/2006 0059,7 09
12:56:51:500 25/09/2006 0062,2 08
12:56:52:000 25/07/2006 0057,7 09
12:56:52:500 25/08/2006 0071,9 09
12:56:08:000 25/07/2006 0065,3 15
12:56:15:000 25/07/2006 0057,7 09
12:56:51:500 25/09/2006 0062,2 08
y'a des tabulations et des espaces pour séparer tout ça.
je dois garder que les codes 08 (à droite), transformer la colonne de gauche en secondes (la on est en HH:MIN:S:MS) et rendre des fichiers traités style donnee_lieu.dat

j'ai embrayé un script, mais c super tendu...
#!/bin/bash
monfich=/home/catto/test.txt
var_monfich='$monfich'
eval cat $var_monfich | awk '{print " " $1 " " $2 " " $3 " " $4 " "}' | grep ' 08 ' | tr ':' ' ' | cut -c2-11,14-25,27-31

ça donne
12 56 51 5 25/09/2006 062,2
12 56 51 5 25/09/2006 062,2
12 56 51 5 26/09/2006 062,2

je bloque complet! et j'ai désespérément besoin d'aide...!
MERCI A TOUS!
Configuration: Windows XP
Firefox 2.0.0.1

13 réponses

Résumé de la discussion

Un utilisateur cherche à traiter donnee_lieu.txt, en ne conservant que les enregistrements dont le code à droite vaut 08 et en convertissant l'heure à gauche en secondes. Plusieurs répondants proposent d'utiliser awk pour extraire le champ horaire et calculer les secondes totales, par exemple awk '$4==08 {split($1,tabl,":"); print tabl[1]*3600+tabl[2]*60+tabl[3]+tabl[4]/1000, $2, $3, $4}' donnee_lieu.txt > resultat.txt. D'autres interventions évoquent des variantes avec grep, sed et boucles Bash, et soulignent l'importance d'éviter les retours chariot Windows pour éviter les erreurs. En pratique, l'essentiel est d'isoler les lignes avec le code 08, de convertir l'heure en secondes et de rediriger le résultat vers un fichier traité.

Bobot (l’IA à votre service)
  1. j'arrive un peu tard mais ça peut peut-être aider quelqu'un

    awk '$4==08 {split($1,tabl,":")
    print tabl[1]*3600+tabl[2]*60+tabl[3]+tabl[4]/1000 ,$2 , $3, $4}' donnee_lieu.txt > resultat.txt

    parce que franchement les scripts plus haut c'est ce compliquer la vie
    1. ok dla balle alors

      l'idée ce serait de donner une ligne de commande suivie du nom du fichier .txt à traiter et le tout renvoyant un fichier du même nom_trai.txt
      en gros

      merci les gars!!!!! :)
      1. Modérateur
        200000 c'est un jeu d'enfant :-DD

        et oui c'est possible, je vais voir ça
        1. je connais pas perl

          mais si ça permet de traiter des fichiers du type
          12:56:15:000 25/07/2006 0059,7 09
          12:56:51:500 25/09/2006 0062,2 08
          12:56:52:000 25/07/2006 0057,7 09
          12:56:52:500 25/08/2006 0071,9 09
          12:56:08:000 25/07/2006 0065,3 15
          12:56:15:000 25/07/2006 0057,7 09
          12:56:51:500 25/09/2006 0062,2 08
          12:56:52:000 08/07/2006 0059,7 09
          12:56:52:500 25/08/2006 0071,9 09
          12:56:08:000 08/07/2006 0065,7 15
          12:56:15:000 25/07/2006 0059,6 09
          12:56:51:500 26/09/2006 0062,2 08
          12:56:52:000 26/07/2006 0052,7 09
          08:56:52:500 26/08/2006 0061,3 09
          08:56:08:000 26/07/2006 0045,3 15

          en très grand nombre et dans les 200000 lignes ça m'intéresse :)
          1. Modérateur
            pour mon amusement je vais voir si je sors une version Perl plus légère ;-)
            1. Modérateur
              Salut à vous,

              pas de problèmes pour moi
              mais il faut d'abord que j'arrive à la maison :-))
              je suis au boulot

              à ce soir vers 19h00
              1. salut!

                ok ça marche

                merci vous êtes super efficaces les gars!
            2. Modérateur
              Malheureusement je n'ai pas Cygwin sous la main.
              Faudrait attendre que quelqu'un ayant une version d'installée et opérationnelle (comme lami20j) passe dans le coin et essaie ça chez lui pour savoir si effectivement ça vient de ta version ou d'ailleurs...

              ;-))
              1. franchement t as déjà grave assuré!

                merci vraiment.

                si jamais tu peux essayer sous cygwin et me dire à l'occas

                je vais cloturer ce pb comme résolu et en creer un nouveau plus spécifique

                merci encore pour ton aide et ta rapidité!!!!
            3. Modérateur
              y'a un truc qui me chiffonne, c'est l'interprétation de la variable "$monfich" :
              monfich="/home/catto/test.txt"
              + monfich=$'/home/catto/test.txt\r'
              Dans son interprétation il met un "$" devant alors qu'il ne devrait pas !!!

              Essaie de virer la variable dans ton script et met directement le chemin et le nom du fichier en lieu et place, et relance le script en mode débogage.
              1. ça donne ça. ça vient de ma version cygwin?

                $ sh -xv trait2
                #!/bin/bash
                sed -n '/08$/p' test.txt > tmp.txt
                + sed -n '/08$/p' test.txt
                : No such file or directory
                while read ligne
                do
                #read ligne
                if [ "$ligne" = "" ]
                then break
                fi
                col=$(echo ${ligne} | awk '{ print $2 " " $3 " "$4 }')
                heure=$(echo ${ligne} | awk -F: '{ print $1 }')
                minute=$(echo ${ligne} | awk -F: '{ print $2 }')
                seconde=$(echo ${ligne} | awk -F: '{ print $3 }')
                mseconde=$(echo ${ligne} | awk -F: '{ print $4 }' | awk '{ print $1 }')
                somme="$(($heure*3600+$minute*60+$seconde)),$mseconde"
                echo "$somme $col" >> test.txt.out
                done < tmp.txt
                trait2: line 16: syntax error near unexpected token 'done'
                'rait2: line 16: 'done < tmp.txt
            4. Modérateur
              Lance ton script en mode débogage, et copie/colle le résultat ici s'il te plait :
              sh -xv trait2
              1. $ sh -xv trait2
                #!/bin/bash
                monfich="/home/catto/test.txt"
                + monfich=$'/home/catto/test.txt\r'
                sed -n '/08$/p' $monfich > tmp.txt
                + sed -n '/08$/p' $'monfich > tmp.txt\r'
                : No such file or directory
                while read ligne
                do
                #read ligne
                if [ "$ligne" = "" ]
                then break
                fi
                col=$(echo ${ligne} | awk '{ print $2 " " $3 " "$4 }')
                heure=$(echo ${ligne} | awk -F: '{ print $1 }')
                minute=$(echo ${ligne} | awk -F: '{ print $2 }')
                seconde=$(echo ${ligne} | awk -F: '{ print $3 }')
                mseconde=$(echo ${ligne} | awk -F: '{ print $4 }' | awk '{ print $1 }')
                somme="$(($heure*3600+$minute*60+$seconde)),$mseconde"
                echo "$somme $col" >> ${monfich}.out
                done < tmp.txt
                rm -f tmp.txt
                trait2: line 17: syntax error near unexpected token 'done'
                'rait2: line 17: 'done < tmp.txt

                C koi la technique pour copier coller???
            5. Modérateur
              Essaie ça alors :
              #!/bin/bash
              monfich="/home/catto/test.txt"
              
              
              sed -n '/08$/p' $monfich > tmp.txt
              while read ligne
              do
              #read ligne
              if [ "$ligne" = "" ]
              then break
              fi
              col=$(echo ${ligne} | awk '{ print $2 " " $3 " "$4 }')
              heure=$(echo ${ligne} | awk -F: '{ print $1 }')
              minute=$(echo ${ligne} | awk -F: '{ print $2 }')
              seconde=$(echo ${ligne} | awk -F: '{ print $3 }')
              mseconde=$(echo ${ligne} | awk -F: '{ print $4 }' | awk '{ print $1 }')
              somme="$(($heure*3600+$minute*60+$seconde)),$mseconde"
              echo "$somme $col" >> ${monfich}.out
              done < tmp.txt
              rm -f tmp.txt
              
              
              1. T es vraiment hallucinant! wao

                la g des erreurs (je suis dans le répertoire de test.txt)

                $ ./trait2
                : No such file or directory
                ./trait2: line 17: syntax error near unexpected token 'done'
                './trait2: line 17: 'done < tmp.txt

                tu penses que ça vient d'où?
            6. Modérateur
              Re-

              Essaie depuis la ligne de commande et depuis le répertoire où se trouve ton fichier "test.txt", de taper çà :
              while read line; do echo "$line" ; done < <(grep "08$" test.txt)
              et dis moi ce que ça répond ;-))
              1. salut!

                aucun message d'erreur affiché. ça a l'air de marcher

                c bon signe?
              2. Modérateur
                As-tu eu ça :
                12:56:51:500 25/09/2006 0062,2 08
                12:56:51:500 25/09/2006 0062,2 08
                
                comme résultat ?
              3. @jipicynon aucun retour écran
                le calcul tourne
                et j'ai de nouveau la main sous cygwin avec le $
            7. Bonjour!

              super merci à gorkimat! t dla balle!

              g encore un problème cependant: j'utilise Cygwin /s Win XP et ce dernier ne comprend pas les do, done et les if, fi alors que les syntaxes sont correctes... il me sort syntax error near unexpected token 'done' et même chose pour 'fi' si je supprime le do/done.

              un mec a déjà eu ce problème apparemment et il a contacté Cygwin sans réponse en matière j'en ai peur...

              voir http://ecos.sourceware.org/ml/cygwin/2001-09/msg00236.html

              voila! si jamais vous avez une idée en tête...

              MERCI ENCORE!
              1. Modérateur
                Salut,

                Essaie avec le même script, mais un peu remanié :
                #!/bin/bash
                monfich=plop.txt
                
                sed -n '/08$/p' $monfich | while true
                do
                read ligne
                if [ "$ligne" = "" ]
                then break
                fi
                col=$(echo ${ligne} | awk '{ print $2 " " $3 " "$4 }')
                heure=$(echo ${ligne} | awk -F: '{ print $1 }')
                minute=$(echo ${ligne} | awk -F: '{ print $2 }')
                seconde=$(echo ${ligne} | awk -F: '{ print $3 }')
                mseconde=$(echo ${ligne} | awk -F: '{ print $4 }' | awk '{ print $1 }')
                somme="$(($heure*3600+$minute*60+$seconde)),$mseconde"
                echo "$somme $col" >> ${monfich}.out
                done
                N'oublie pas d'ajuster la variable "monfich" avec le nom de ton fichier...

                ;-))
              2. @jipicySalut!

                Je suis super impressionné par la rapidité de tes réponses: MERCI!

                Ton script a l'air nickel en plus.

                Ce qui se passe maintenant c'est que Cygwin ne reconnait pas les boucles do et if je comprends pas pkoi...

                le fichier trait2 se présente donc comme tu l'as fait:

                #!/bin/bash
                monfich=/home/catto/test.txt
                sed -n '/08$/p' $monfich | while true
                do
                read ligne
                if [ "$ligne" = "" ]
                then break
                fi
                col=$(echo ${ligne} | awk '{ print $2 " " $3 " "$4 }')
                heure=$(echo ${ligne} | awk -F: '{ print $1 }')
                minute=$(echo ${ligne} | awk -F: '{ print $2 }')
                seconde=$(echo ${ligne} | awk -F: '{ print $3 }')
                mseconde=$(echo ${ligne} | awk -F: '{ print $4 }' | awk '{ print $1 }')
                somme="$(($heure*3600+$minute*60+$seconde)),$mseconde"
                echo "$somme $col" >> ${monfich}.out
                done


                je le lance dans Cygwin par ./trait2 normal

                et il me dit:
                ./trait2: line 16: syntax error near unexpected token 'done'
                ./trait2: line 16: 'done'

                si j'enlève le do et le done il fait pareil mais avec "fi"

                Merci une fois encore pour ton aide. Si jamais t'as une idée là-dessus...
            8. Bonjour,

              Il y a peut-être plus condensé, mais c'est déjà un début et a adapter.

              #!/bin/bash
              monfich=MonFic.txt
              var_monfich='$monfich'

              cat < MonFic.txt | while true
              do
              read ligne
              if [ "$ligne" = "" ]; then break; fi
              if [ `echo ${ligne} | awk '{print $4}'` -eq 08 ];
              then
              heure=`echo ${ligne} | awk '{print $1}' | cut -d: -f1`
              minute=`echo ${ligne} | awk '{print $1}' | cut -d: -f2`
              seconde=`echo ${ligne} | awk '{print $1}' | cut -d: -f3`
              mseconde=`echo ${ligne} | awk '{print $1}' | cut -d: -f4`
              # Miliseconde à ajouter
              somme=$(($heure*3600+$minute*60+$seconde))
              echo "$somme `echo ${ligne} | awk '{print $2 " " $3 " "$4}'`" >> ${monfich}.out
              fi
              done

              Bon courage
              1. c bien comme solution , dis moi je connais pas détout le script shell et j'ai envie d'apprendre un peu t'es peu me conseiller d'aller sur que site pour commencer
              2. @mounirquelques sites sympas

                http://www.ac-creteil.fr/reseaux/systemes/linux/shell-scripts/filtres.html

                http://www.ac-creteil.fr/reseaux/systemes/linux/shell-scripts/shell-programmation.html

                http://perso.orange.fr/dorian.linux/bash.html

                https://www.linux-pour-lesnuls.com/#introduction