IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Calcul avec AWK


Sujet :

Shell et commandes GNU

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Par défaut Calcul avec AWK
    Bonjour à tous,

    J’essaie de faire un petit script qui évalue certains champs d'un CSV.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla

    J'ai un premier jet qui fonctionne pas trop mal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    awk -F ',' 'function CALC( F ) {system ("echo \"" $F "\" | bc -l | tr -d \"\\n\"")} { for(i=1 ; i <= 13 ; i++) { printf "%s,",$i } ; CALC( 14 ); for(i=16 ; i <= NF ; i++) { printf "%s", ","$i }; print "\n"}' fichier.csv
    Mon problème est que cela est très,très long ....

    A priori avec printf, c'est bien plus rapide, mais impossible de le faire fonctionner...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    awk -F ',' 'function CALC( F ) {printf "%.3f\n", $F} { for(i=1 ; i <= 13 ; i++) { printf "%s,",$i } ;  CALC( 14 ); print "\n"}' fichier.csv
    Le $F contient bien ma chaine mais le retour = 0.000

    Voilà.

    Si l'un de vous a des idées, je suis preneur.

    Merci.

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 673
    Par défaut
    Bonjour,

    je pensais que strtonum aurait évalué la chaîne, mais non.
    alors j'ai fait un peu de stfw :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gawk 'BEGIN{FS=OFS=","}{"echo \""$3"\"| bc -l"|getline var; $3=var}1' tonFichier
    recourir au shell dans awk me rend chagrin.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Par défaut
    Bonjour N_BaH,

    Merci pour ton retour. Ca fonctionne très bien et c'est bien plus jolie que ma première tentative ^^
    Cependant, le temps de traitement est toujours très long, enfin je suppose qu'il est "normal" avec un bc.

    J'ai donc une autre question, bc est-il le moyen le plus rapide de calculer des floats en shell ?
    Dans mon cas j'ai environ 2,5 millions d'enregistrement à traiter et j'aimerai être dans les 30min (la à priori entre 45min et 1H de traitement ).

    Merci.

  4. #4
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 376
    Par défaut
    Une variante plus barbare toujours avec bc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo 'blablabla,blablabla,(47+(34/60)+(54.42/3600)),blabla,blabla' | awk -F ',' 'BEGIN{OFS=FS}"bc -l <<<\""$3"\"" | getline $16'
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blabla,blabla,,,,,,,,,,,47.58178333333333333332
    Et une version perl (peut-être plus rapide) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo 'blablabla,blablabla,(47+(34/60)+(54.42/3600)),blabla,blabla' | perl -F',' -ane '$,=",";chomp @F;print @F,",,,,,,,",(eval "$F[2]")."\n"'
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blabla,blabla,,,,,,,,,47.5817833333333

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 673
    Par défaut
    le shell ne sait pas calculer les nombres à virgule.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Il me semble qu'il y a quand même plus performant, sans appeler l'évaluation à chaque ligne.
    Puisque le champ contenant les opérations est apparemment toujours à la même place :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d=','; c=3; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' f) <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' f)) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' f)
    Ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ cat f
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    $ d=','; c=3; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' f) <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' f)) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' f)
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla
    $
    Si le champ contenant les opérations n'est pas toujours à la même place, il faut savoir comment le repérer, et mettre ça dans les différents awk : ça ne me semble pas poser de problème à priori.

  7. #7
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 673
    Par défaut
    sur 6M de lignes, la ligne de code, que j'ai trouvée en fouinant le net, est trois fois plus rapide.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 376
    Par défaut
    Une version spéciale gawk:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gawk -F ',' 'BEGIN{OFS=FS}{print $3 |& "bc -l" ; "bc -l" |& getline $16}1' fichier
    Ici, gawk crée un sous process bc sur lequel il pipe l'entrée et la sortie, un seul process bc est lancé pour toute la lecture du fichier.

    Dans l'exemple présenté ici, on envoi sur l'entrée et on récupère tout de suite la sorti de bc, mais rien n'empêche de faire d'autres actions entre les deux.

  9. #9
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 673
    Par défaut
    pourquoi $16 ?
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  10. #10
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    sur 6M de lignes, la ligne de code, que j'ai trouvée en fouinant le net, est trois fois plus rapide.
    Je pense que c'est parce que tu as mis 6M de fois la même ligne dans le fichier (ou plus exactement 6M de fois le même champ à calculer)
    Du coup, c'est toujours le même « fichier » "echo \""$3"\"| bc -l" que awk utilise, c'est-à-dire toujours le même process.
    Mais si tu mets un champ différent pour chaque ligne, tu vas voir que les temps de calcul vont exploser.
    En fait, ils vont être ceux que tu obtiendrais en fermant le « fichier » à chaque ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gawk 'BEGIN{FS=OFS=","}{"echo \""$3"\"| bc -l"|getline var; close("echo \""$3"\"| bc -l"); $3=var}1' tonFichier
    Citation Envoyé par disedorgue Voir le message
    Une version spéciale gawk:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gawk -F ',' 'BEGIN{OFS=FS}{print $3 |& "bc -l" ; "bc -l" |& getline $16}1' fichier
    Ici, gawk crée un sous process bc sur lequel il pipe l'entrée et la sortie, un seul process bc est lancé pour toute la lecture du fichier.

    Dans l'exemple présenté ici, on envoi sur l'entrée et on récupère tout de suite la sorti de bc, mais rien n'empêche de faire d'autres actions entre les deux.
    Là par contre, il n'y a bien qu'un seul process, même pour des lignes différentes, mais j'obtiens de meilleurs résultats avec la « méthode paste » :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    $ for ((i=1;i<1000;i++)); do echo "blablabla,blablabla,($i+(34/60)+(54.42/3600)),blablabla,blabla"; done >f
    $ time gawk -F ',' 'BEGIN{OFS=FS}{print $3 |& "bc -l" ; "bc -l" |& getline $3}1' f >/dev/null
     
    real	0m0,192s
    user	0m0,080s
    sys	0m0,060s
    $ time { d=','; c=3; f=f; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' "$f") <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' "$f")) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' "$f"); } >/dev/null
     
    real	0m0,149s
    user	0m0,069s
    sys	0m0,033s
    $
    $ for ((i=1;i<10000;i++)); do echo "blablabla,blablabla,($i+(34/60)+(54.42/3600)),blablabla,blabla"; done >f
    $ time gawk -F ',' 'BEGIN{OFS=FS}{print $3 |& "bc -l" ; "bc -l" |& getline $3}1' f >/dev/null
     
    real	0m1,090s
    user	0m0,460s
    sys	0m0,331s
    $ time { d=','; c=3; f=f; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' "$f") <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' "$f")) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' "$f"); } >/dev/null
     
    real	0m0,756s
    user	0m0,382s
    sys	0m0,154s
    $
    $ for ((i=1;i<100000;i++)); do echo "blablabla,blablabla,($i+(34/60)+(54.42/3600)),blablabla,blabla"; done >f
    $ time gawk -F ',' 'BEGIN{OFS=FS}{print $3 |& "bc -l" ; "bc -l" |& getline $3}1' f >/dev/null
     
    real	0m11,568s
    user	0m5,125s
    sys	0m3,762s
    $ time { d=','; c=3; f=f; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' "$f") <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' "$f")) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' "$f"); } >/dev/null
     
    real	0m7,800s
    user	0m3,796s
    sys	0m1,926s
    $
    $ for ((i=1;i<1000000;i++)); do echo "blablabla,blablabla,($i+(34/60)+(54.42/3600)),blablabla,blabla"; done >f
    $ time gawk -F ',' 'BEGIN{OFS=FS}{print $3 |& "bc -l" ; "bc -l" |& getline $3}1' f >/dev/null
     
    real	1m45,943s
    user	0m58,371s
    sys	0m51,735s
    $ time { d=','; c=3; f=f; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' "$f") <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' "$f")) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' "$f"); } >/dev/null
     
    real	0m41,250s
    user	0m35,226s
    sys	0m18,054s
    $

  11. #11
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 673
    Par défaut
    Mais si tu mets un champ différent pour chaque ligne, tu vas voir que les temps de calcul vont exploser.
    En fait, ils vont être ceux que tu obtiendrais en fermant le « fichier » à chaque ligne
    bien vu.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  12. #12
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 376
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    pourquoi $16 ?
    Comme ça... j'aurais pu mettre $3 pour écraser la formule par la valeur

  13. #13
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 673
    Par défaut
    une fantaisie !
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  14. #14
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 376
    Par défaut
    Citation Envoyé par mercosivo Voir le message
    J'ai donc une autre question, bc est-il le moyen le plus rapide de calculer des floats en shell ?
    Dans mon cas j'ai environ 2,5 millions d'enregistrement à traiter et j'aimerai être dans les 30min (la à priori entre 45min et 1H de traitement ).
    Alors, faut que tu nous donnes plus d'éléments, parce que les tests que je donne plus bas sont en dessous de la minutes pour 2,5 millions de lignes...
    Citation Envoyé par balkany Voir le message
    Là par contre, il n'y a bien qu'un seul process, même pour des lignes différentes, mais j'obtiens de meilleurs résultats avec la « méthode paste » :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ wc -l /tmp/f
    2500000 /tmp/f
    $ time awk -F ',' 'BEGIN{OFS=FS} {print $3 |& "bc -l" ; "bc -l" |& getline $3}1' </tmp/f >/dev/null 
     
    real	0m45,261s
    user	0m28,788s
    sys	0m25,575s
    $ time { d=','; c=3; f=/tmp/f; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' "$f") <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' "$f")) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' "$f"); } >/dev/null 
     
    real	0m11,591s
    user	0m25,234s
    sys	0m8,162s
    $ time perl -F"," -ane '$,=",";$F[2]=eval "$F[2]";print @F' /tmp/f >/dev/null 
     
    real	0m19,611s
    user	0m19,517s
    sys	0m0,068s
    Dans les faits, en monoproc/monothread, le plus rapide est le perl, en multiproc/multithread c'est la version paste de Balkani car celle-ci exécute en parallèle bc et les awk dont les sorties sont rassemblées par paste.

    Par contre, ma version gawk étant totalement séquentiel, elle est la plus lente mais on est tout de même loin des 45 minutes.

  15. #15
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Par défaut
    Merci a tous, pour votre aide.
    Je test tout ça demain et je vous fait un retour.

    Encore merci.

    [Edit]

    Bon finalement j'ai quand même fait un test sur 100000 enregistrements.
    La méthode de balkany est impressionnante en terme de rapidité (je n'ai pas timé mais moins de 2s pour les 100000 enregistrements).

    Je vais le test demain sur le fichier complet et je clôturerai le sujet.

    Merci beaucoup.

  16. #16
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Par défaut
    Bonjour,

    Finalement la solution de balckany ne fonctionne pas dans mon cas (ou alors je m'y prends comme un pied...).
    Grosso modo tant qu'il n'y a pas beaucoup d'enregistrement cela fonctionne.
    Par contre sur le fichier total, lorsqu'un champ correspondant à la variable $c est vide cela "plante" et un résultat est quand même renseigné en sorti.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    exemple :
    BlaBla,BlaBla,BlaBla,BlaBla,,,,,,,,,,,,,,,BlaBla,BlaBla,BlaBla,BlaBla,BlaBla,BlaBla,
     
    ressort en :
     
    BlaBla,BlaBla,BlaBla,BlaBla,,,,,,,,,,48.84626944444444444444,,,,,,BlaBla,BlaBla,BlaBla,BlaBla,BlaBla,BlaBla,
    J'ai utilisé le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    d=','; c=14; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' fichier) <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' fichier) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' fichier)
    Je n'arrive vraiment pas a comprendre ce comportement, ma ligne est fausse ? (j'ai pourtant recopier celle de balckany ...)

    Pour info je peux avoir des enregistrements de plusieurs type :
    -Toujours 25 champs par lignes
    -Le calcule est toujours sur le champs 14
    -Certains champs peuvent être vide (y compris le champ 14)

    Voilà,
    Si vous avez une idée, je suis toujours preneur.


    PS : en regardant de plus près, il semblerai qu'il y ai un switch entre certaine ligne avec $14 et $14plein... je n'ai pas encore compris la logique
    Merci.

  17. #17
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Par défaut
    Finalement, je n'avais pas les yeux en face des trous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    [root@monserveur tmp]# cat f
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    blablabla,blablabla,,blablabla,blabla
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    [root@monserveur tmp]#
    [root@monserveur tmp]#
    [root@monserveur tmp]#
    [root@monserveur tmp]# d=','; c=3; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' f) <(bc -l < <(awk -F"$d" -vc=$c '{print $c}' f))
    blablabla,blablabla,47.58178333333333333332
    blablabla,blablabla,47.58178333333333333332
    blablabla,blablabla,47.58178333333333333332
    blablabla,blablabla,47.58178333333333333332
    blablabla,blablabla,
    [root@monserveur tmp]#

    ça me rassure, je ne suis pas fou, ouf
    Il y a bien une inversion

  18. #18
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Ah ben oui, après il faut savoir adapter un peu si besoin
    Comme je disais en #6 par exemple, si le champ à calculer n'était pas toujours à la même position, il faudrait mettre une reconnaissance de champ dans les différents awk.

    Ici il faut gérer les champs vides : le problème vient de bc, qui ignore simplement les lignes vides, ce qui te met ensuite un décalage dans la reconstruction par paste.
    Une possibilité est de forcer bc à imprimer les lignes vides : cf. man bc :
    The string is printed to the output. Strings start with a double quote character and contain all characters until the next double quote character. All characters are take literally, including any newline. No newline character is printed after the string.
    Donc on peut mettre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bc -l < <(awk -F"$d" -vc=$c '$c==""{print "\"\n\""; next} {print $c}' "$f")
    Puis tu injectes ça dans la commande globale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d=','; c=14; f=fichier; paste -d"$d" <(awk -F"$d" -vc=$c '{for(i=1;i<=c-2;i++) printf("%s"FS,$i); printf("%s\n",$i)}' "$f") <(bc -l < <(awk -F"$d" -vc=$c '$c==""{print "\"\n\""; next} {print $c}' "$f")) <(awk -F"$d" -vc=$c '{for(i=c+1;i<=NF-1;i++) printf("%s"FS,$i); printf("%s\n",$NF)}' "$f")

  19. #19
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Par défaut
    Hello Balckany,

    C'est bien mieux effectivement, merci.
    Cette commande bc m'aura donné bien du mal...
    J'ai appris énormément de chose via ce thread, merci à vous

  20. #20
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par mercosivo Voir le message
    J’essaie de faire un petit script qui évalue certains champs d'un CSV.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    blablabla,blablabla,(47+(34/60)+(54.42/3600)),blablabla,blabla
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    blablabla,blablabla,47.58178333333333333332,blablabla,blabla
    Quand je vois ça, ça me fait penser à quelqu'un qui essaierait de transformer "47 heures, 34 minutes et 54.42 secondes" en "47.58178333333333333332 heures".

    Je ne sais pas s'il existe des fonctions plus rapides que les 2 divisions et les sommes...

    J'ai aussi un peu de mal à imaginer dans quel contexte il serait véritablement et sensément indispensable d'avoir ce format pour le moins non conventionnel.

    Bref, si c'était mon projet, je changerais le process qui génère le fichier pour:
    - soit lui faire mettre dans 3 champs séparés les heures, minutes et secondes
    - soit lui faire faire lui-même le calcul et mettre le résultat dans le champ!

    Évidemment, comme d'habitude, j'imagine qu'il est fort probable que le changement de format du fichier ne soit pas une option envisageable...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 17
    Dernier message: 28/07/2017, 23h08
  2. Réponses: 7
    Dernier message: 17/02/2012, 11h57
  3. Réponses: 33
    Dernier message: 15/10/2004, 16h19
  4. Problème sur une cmd avec AWK
    Par OrangeBud dans le forum Linux
    Réponses: 3
    Dernier message: 02/06/2004, 10h51
  5. Réponses: 2
    Dernier message: 22/03/2004, 10h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo