Calculer le nombre d'occurence en bash

Fermé
boubou95 - 17 juin 2010 à 10:14
 boubou95 - 17 juin 2010 à 15:56
Bonjour,

J'aimerais savoir comment je peut faire pour au début calculer le nombre de ; de chaque ligne dans un fichier, stocker le maximum de ; par ligne dans une variable, ensuite refaire une boucle pour trouver les lignes qui n'ont pas le maximum de point virgule et en rajouter dans la ligne et tout cela en bash. Comme ci dessous:

"09.03.10";"18:31:53";23,01;0,21;167,2;1016,9;2 ;17 ;-3,4 ;2,9
"09.03.10";"18:31:54";23,01;0,21;167,1;1016,9;2, ;17 ;-3,4 ;2,9
"09.03.10";"18:31:55";23,01;0,21;167,2;1016,9;2, ;17 ;-3,4;2,9
"09.03.10";"18:31:56";23,01;0,22;167,2;1016,8;2, ;17 ;-3,4;2,9
"09.03.10";"22:50:55";23,
"09.03.10";"22:50:56";23,
"09.03.10";"22:50:57";23,
"09.03.10";"22:50:58";23,
"09.03.10";"22:50:59";23,

ce qui doit donner:

"09.03.10";"18:31:53";23,01;0,21;167,2;1016,9;2 ;17 ;-3,4 ;2,9
"09.03.10";"18:31:54";23,01;0,21;167,1;1016,9;2, ;17 ;-3,4 ;2,9
"09.03.10";"18:31:55";23,01;0,21;167,2;1016,9;2, ;17 ;-3,4;2,9
"09.03.10";"18:31:56";23,01;0,22;167,2;1016,8;2, ;17 ;-3,4;2,9
"09.03.10";"22:50:55";;;;;;;;23,
"09.03.10";"22:50:56";;;;;;;;23,
"09.03.10";"22:50:57";;;;;;;;23,
"09.03.10";"22:50:58";;;;;;;;23,
"09.03.10";"22:50:59";;;;;;;;

Tout ceci se trouve dans un fichier texte.
Merci d'avance de votre aide, car là je suis vraiment bloqué :-S.

3 réponses

dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
17 juin 2010 à 12:45
hello
$ awk 'BEGIN{FS=OFS=";"};{if(n<NF)n=NF;f[NR]=$0};END{for(i=1;i<=NR;i++){$0=f[i];m=NF;while(m++<n)$NF=OFS $NF ; print}}' fichier
"09.03.10";"18:31:53";23,01;0,21;167,2;1016,9;2 ;17 ;-3,4 ;2,9
"09.03.10";"18:31:54";23,01;0,21;167,1;1016,9;2, ;17 ;-3,4 ;2,9
"09.03.10";"18:31:55";23,01;0,21;167,2;1016,9;2, ;17 ;-3,4;2,9
"09.03.10";"18:31:56";23,01;0,22;167,2;1016,8;2, ;17 ;-3,4;2,9
"09.03.10";"22:50:55";;;;;;;;23,
"09.03.10";"22:50:56";;;;;;;;23,
"09.03.10";"22:50:57";;;;;;;;23,
"09.03.10";"22:50:58";;;;;;;;23,
"09.03.10";"22:50:59";;;;;;;;23,
$ 
1
Merci beaucoup je vais immédiatement tester.
0
ca marche niquel !encore merci. Par conte je suis dans l'apprentissage du bash pourrais tu m'expliquer la ligne de commande que je la comprenne et puisse la réutiliser plus tard pour d'autre application? Merci de ton aide
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
17 juin 2010 à 14:48
on pourrait faire en bash, mais là j'utilise awk
BEGIN{FS=OFS=";"} on definit ; comme séparateur de champ
{if(n<NF)n=NF;f[NR]=$0} on sauve dans n la plus grande valeur de NF (qui est le nombre de champ par ligne) et on stocke chaque ligne dans un tableau f, NR est le numéro de ligne. Il faut lire tout le fichier pour trouver le plus grand NF
END{for(i=1;i<=NR;i++) après la fin de la lecture du fichier (END), on traite le tableau qui contient chaque ligne, NR est le nombre de lignes
{$0=f[i];m=NF;while(m++<n)$NF=OFS $NF ; print}} tant que le nombre de champ d'une ligne (NF) est plus petit que n (le nombre de champs le plus grand), on concatène un ; avant le dernier champ puis on imprime la ligne; print sans paramètre = print $0
1
Merci beaucoup pour toutes ces explications.
Comment je peux faire pour concaténer ; après le deuxième champs et non avant le dernier champ?
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
Modifié par dubcek le 17/06/2010 à 15:40
remplacer $NF=OFS $NF par $2=$2 OFS
0
Merci beaucoup! Je vais vous embeter une dernière fois :-S, j'ai un fichier comme cela:

"";
"TempAmb";"Anemometre";"Girouette";"PresAtm";"PSolaire";"Hu";"TempRosee";"Eau/Air";
"NiCr";
"Ntc";"D260";"D260";"D2.6";"D2.6";"%rH";"HDT";"HAH";
"M00:øC";
"M00:øC";"M01:ms";"M02:ø";"M03:mb";"M04:Wm";"M10:%H";"M20:øC";"M30:gk";
;
;
;
;
0,;;

et un fichier comme cela:

"2590-9";"COMMENT:"
"ALMEMO";"RANGE:"
"DATE:";"TIME:"
"MODUL:00";"LIM-MIN:"
"NUMBER:";"00-000"
"V5";"LIM-MAX:"

J'aimerais que ça fasse cela:

"2590-9";"COMMENT:";"TempAmb";"Anemometre";"Girouette";"PresAtm";"PSolaire";"Hu";"TempRosee";"Eau/Air";"";
"ALMEMO";"RANGE:""Ntc";"D260";"D260";"D2.6";"D2.6";"%rH";"HDT";"HAH";"NiCr";
"DATE:";"TIME:";"M00:øC";"M01:ms";"M02:ø";"M03:mb";"M04:Wm";"M10:%H";"M20:øC";"M30:gk";"M31:øC";
"MODUL:00";"LIM-MIN:";
"NUMBER:";"00-000";
"V5";"LIM-MAX:";

Donc dans un premier temps que la ligne une du fichier 1 se mette à la fin de la ligne deux du fichier 1, ligne 3 à la fin de la ligne4... Tout cela dans un même fichier, et qu'ensuite qu'on colle le fichier 1 à coté du fichier 2, mais je ne sais pas comment le traduire en bash...

Merci de votre aide.
0
awk et bash sont deux programmes différents.
bash est un interpréteur de commandes qui exécute les commandes lues depuis l'entrée standard ou depuis un fichier.
awk est un langage de recherche de motif et de traitement.

Sur des fichiers (très) volumineux, il vaut mieux utiliser awk, qui est plus rapide. Il est fait pour ça !

mais si tu veux apprendre bash :
#!/bin/bash
fichier=./fichier 
while read line; do  
   npunct="${line//[^;]/}"  
   npunct="${#npunct}"  
   if (( ! pnpunct || npunct > pnpunct )); then pnpunct="$npunct"; fi  
done <$fichier  

while IFS=';' read -a line; do  
   npunct=$((${#line[@]} - 1))  
   if (( npunct < pnpunct )); then  
      toadd=$(( pnpunct - npunct ))  
      printf '%s;' "${line[@]::npunct}"  
      for (( i=0; i < toadd; i++ )); do printf ";"; done  
      printf '%s\n' "${line[@]: -1}"  
   else  
      line=$(printf '%s;'  "${line[@]}")  
      echo -ne "${line}\b \n"
   fi  
done <$fichier
1
Merci pour ton aide, mais ça ma l'air assez compliqué moi qui n'y connait pas grand chose :-)par rapport a ce que dubcek a écrit en plus ça marche niquel. Mais j'imagine que ça c'est du vrai bash, c'est ça? Alors que dubcek a utilisé une fonction existante. Mais merci encore
0