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

Unix Discussion :

Problème avec commande awk : lecture puis modification zone dans un fichier


Sujet :

Unix

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 81
    Points
    81
    Par défaut Problème avec commande awk : lecture puis modification zone dans un fichier
    Bonjour,

    N'étant pas "un professionnel" des commandes shell/unix je vous expose mon problème en espérant être assez clair.
    J'écris un script qui lit un fichier en entrée pour récupérer une zone ($7) puis je souhaite scripter cette zone et recopier le fichier en entrée dans un nouveau fichier avec cette même zone mise à jour (scriptée).
    Mais je rencontre le message suivant dans mon script shell :
    awk: Field is not correct.
    The input line number is 1.
    The source line number is 1.

    Voici mon script :
    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
    vCheminFXOT=/fic/stbc${instance}/00Y/FXOT
    vFicOut=${vCheminFXOT}/FicEntree.csv
     
    echo $vFicOut
     
    cat ${vFicOut} | while read ligne
    do  
       echo "Ligne : " $ligne
       matricule=`echo $ligne | awk -F"\|" '{print $7}'`
       echo "matricule : " $matricule
       cryptage=$(printf $matricule | openssl dgst -binary -sha256 | openssl base64)
       echo "cryptage : " $cryptage
       echo $ligne | awk -F"|" 'BEGIN{OFS="|"} {$7=$cryptage} {print $0}' >> FicSortie.csv
       echo "Ligne MAJ : " $ligne
    done 
     
    exit
    -------------------
    Exemple de ligne dans mon fichier et ce que je souhaite ==> cryptage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Ligne :  01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|1234567899999|19620902|1|54|NC|M|691|01|1234567899999|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    matricule :  1234567899999
    cryptage :  AwOnndlQG77RqLrHEXr3NiuCef+DAjca2cEip6f2zxE=
    ------------------

    Auriez-vous une idée ?

    Merci pour votre aide...

  2. #2
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    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 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Bonjour,

    Utilise la balise code pour les ligne de script (le bouton avec le '#') ...

    Sinon, ton souci semble être sur la ligne ci-dessous avec le souci en rouge:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $ligne | awk -F"|" 'BEGIN{OFS="|"} {$7=$cryptage} {print $0}' >> FicSortie.csv
    Qui n'est pas reconnu par awk, ici c'est une variable shell mais awk ne la voit pas comme ça et le shell ne la traduira pas puisque ta chaine est entre simple quote...

    une solution potentielle (pas testé):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $ligne | awk -F"|" -vcryptage="$cryptage" 'BEGIN{OFS="|"} {$7=cryptage} {print $0}' >> FicSortie.csv
    Sinon, par curiosité, tu as quelle volumétrie à faire comme ça ?
    car c'est loin d'être rapide et je te conseillerais plutot perl ou python si tu as une énorme volumétrie (plusieurs millions).
    Cordialement.

  3. #3
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Bonjour

    Pas besoin d'attendre d'être professionnel pour utiliser les bons mots: ton "scripter", en français, c'est "chiffrer". Rien à voir avec les scripts, donc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "matricule : " $matricule
    J'aime bien cette ligne. Tu protèges, par des double quotes, ce qui est fixe, et tu ne protèges pas ce qui est variable.
    Le conseil est évidemment de faire l'inverse. Ou de tout protéger.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "matricule : $matricule"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $ligne | awk -F"|" 'BEGIN{OFS="|"} {$7=$cryptage} {print $0}' >> FicSortie.csv
    Et puisqu'on parle de protection, les simples quotes ' empêchent l'interprétation des variables.
    Donc si tu crois que $cryptage va être remplacé, tu te trompes.
    Je n'ai pas testé mais il est possible que awk considère la variable cryptage à 0, et donc $cryptage est équivalent à $0, c'est-à-dire toute la ligne.

    Pour transmettre une variable de bash à awk on utilise généralement l'option -v.
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F';' -vmavariable=$PATH '{print mavariable;}' fichier
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  4. #4
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    pour le fun*, tout en awk :
    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
    awk -F'|' '
       BEGIN {
          OFS="|"
          cmd="openssl dgst -binary -sha256 | openssl base64";
       }
       {
          printf("matricule   : %s\nchiffration : ", $7);
          printf("%s", $7) |& cmd;
          close(cmd, "to");
          cmd |& getline $7;
          close(cmd, "from");
          print $7;
          print $0 >> "FicSortie.csv";
       }
    ' fichier
    l'exécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    matricule   : 1620913005383
    chiffration : 9pmQyFNbr6djyeWw0THdcaM/sHKEDA3lY7iBZ5073jI=
    matricule   : 3162091300538
    chiffration : 1dwhiB9eAvAiaBWHDjqvChOTZj0Ww5aSiRUffvODKuc=
    matricule   : 8316209130053
    chiffration : dxFQ3TpvQEJwHj17OhYUxhN6qLn3RRb2fSVQ05W3fSA=
    et le fichier FicSortie.csv :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|9pmQyFNbr6djyeWw0THdcaM/sHKEDA3lY7iBZ5073jI=|19620902|1|54|NC|M|691|01|1620913005383|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|1dwhiB9eAvAiaBWHDjqvChOTZj0Ww5aSiRUffvODKuc=|19620902|1|54|NC|M|691|01|1620913005383|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|dxFQ3TpvQEJwHj17OhYUxhN6qLn3RRb2fSVQ05W3fSA=|19620902|1|54|NC|M|691|01|1620913005383|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    sinon comme indiqué plus haut, invoquer continuellement 2 instances de openssl peut avoir un cout important selon le volume de donnée et opter pour un langage plus efficace peut alors être pertinent



    * ne sachant pas si gawk est dispo ni même si la communication bidirectionnelle avec un autre processus est spécifique à gawk

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 81
    Points
    81
    Par défaut Problème avec commande awk : lecture puis modification zone dans un fichier
    Bonjour,

    Merci à vous tous pour votre aide, j'ai testé la formule de "disedorgue" qui marche très bien d'autant plus que je ne traite pas des millions de lignes je suis sur environ 150000 rows.

    Comme merci...

    Cordialement

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 81
    Points
    81
    Par défaut Problème avec commande awk : lecture puis modification zone dans un fichier
    Désolé, je vous relance sur le sujet car j'ai testé sur un fichier plus conséquent (55000rows) et le traitement est assez long... (20min)

    Auriez-vous une solution pour optimiser le script si possible sans changer de langage ?

    Merci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    echo $vFicOut
     
    cat ${vFicOut} | while read ligne
    do  
        matricule=`echo $ligne | awk -F"\|" '{print $7}'`
        cryptage=$(printf $matricule | openssl dgst -binary -sha256 | openssl base64)
        echo $ligne | awk -F"|" -vcryptage="$cryptage" 'BEGIN{OFS="|"} {$7=cryptage} {print $0}' >> FicSortie.csv
    done 
     
    exit

  7. #7
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    Citation Envoyé par samy37 Voir le message
    Auriez-vous une solution pour optimiser le script si possible sans changer de langage ?
    ben... non
    tu veux optimiser quoi, y'a 5 lignes et quasiment que des écho, c'est les aller-retour avec openssl qui prennent du temps, ça et les boucles bash sont connues pour être assez lentes également, navré...

    t'as essayé mon script (full (g)awk) ? des fois que ça aide un peu...

  8. #8
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    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 280
    Points : 12 729
    Points
    12 729
    Par défaut
    As-tu une raison particulière de ne pas vouloir changer de langage ?
    Sachant que si on garde celui-ci, donc script shell + openssl, on devra tout de même faire une réécriture complète pour peut-être passer à moins de 5 minutes, alors qu'en perl ou python, on devrait descendre à je pense la minute et la maintenance serait moins complexe.

    Une discussion similaire sur le sujet: https://www.developpez.net/forums/d1...if-mots-passe/
    Cordialement.

  9. #9
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    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 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Allez, pour 5 minutes de récrée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ perl -MDigest::SHA=sha256 -MMIME::Base64 -a -F'\|' -ne '$,="|";chomp($F[6]=encode_base64(sha256($F[6])));print @F' fichier 
    01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|9pmQyFNbr6djyeWw0THdcaM/sHKEDA3lY7iBZ5073jI=|19620902|1|54|NC|M|691|01|1620913005383|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|1dwhiB9eAvAiaBWHDjqvChOTZj0Ww5aSiRUffvODKuc=|19620902|1|54|NC|M|691|01|1620913005383|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    01.00.00|BCMP_A|C_ACCUEIL_PHYSIQUE|NC||170817|dxFQ3TpvQEJwHj17OhYUxhN6qLn3RRb2fSVQ05W3fSA=|19620902|1|54|NC|M|691|01|1620913005383|19620902|1|54|NC|M|CONTACT|CONTACT|NC|NC|3452755690|NC
    Cordialement.

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur décisionnel
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 81
    Points
    81
    Par défaut Problème avec commande awk : lecture puis modification zone dans un fichier
    Bonjour,

    Merci pour vos réponses, le langage est effectivement une contrainte... Je vais voir si je peux faire autrement

    Merci

  11. #11
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    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 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Suite à la neige, j'ai un peu de temps à passer sur ton problème, donc voici une version plus rapide en shell, openssl et awk mais je ne garanti pas qu'elle fonctionne bien sur ton environnement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/bin/bash
    mkfifo outin0 outin1 in0 in1 out0 out1
    openssl < <(awk 'BEGIN{while(1){print "base64 -in outin0 -out out0\nbase64 -in outin1 -out out1"}}') > /dev/null &
    openssl < <(awk 'BEGIN{while(1){print "dgst -binary -out outin0 -sha256 in0\ndgst -binary -out outin1 -sha256 in1"}}') > /dev/null &
     
    while IFS="|" read a1 a2 a3 a4 a5 a6 a7 a8  ; do echo -n $a7 >in$((h%2)) ; read X <out$((h++%2)) ; echo "$a1|$a2|$a3|$a4|$a5|$a6|$X|$a8" ; done < fichier
     
    exec 2>/dev/null
    jobs -p | xargs kill
    rm -f outin0 outin1 in0 in1 out0 out1
    Sur la machine qui m'a servi de test:

    Durée de ce script pour 10000:
    real 0m4,927s
    user 0m2,344s
    sys 0m3,032s

    Durée de ton script pour 10000:
    real 2m41,213s
    user 1m18,656s
    sys 0m17,728s

    Si tu as des questions, n'hésite pas...
    Cordialement.

  12. #12
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    propre.

  13. #13
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    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 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Mouais, mais je ne sais pas si c'était une bonne idée de donner cette solution...

    Sur mon poste de test:
    55000 itérations via le script de samy37:
    real 15m11,476s
    user 7m12,852s
    sys 1m37,460s

    55000 itérations via le script précédent:
    real 0m30,362s
    user 0m14,208s
    sys 0m17,052s

    55000 itérations via l'uniligne perl:
    real 0m0,988s
    user 0m0,952s
    sys 0m0,032s

    La solution perl est vraiment plus avantageuse, les autres solutions c'est juste pour du jetable.
    Cordialement.

  14. #14
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    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 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Petit détail pratique, pour ne pas avoir du nettoyage de process et/ou de fifo à faire en cas d'interruption du script, il serait mieux de rajouter en début de script la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    trap 'exec 2>/dev/null;jobs -p | xargs kill;rm -f outin0 outin1 in0 in1 out0 out1' EXIT
    et de retirer les 3 dernières lignes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    exec 2>/dev/null
    jobs -p | xargs kill
    rm -f outin0 outin1 in0 in1 out0 out1
    Cordialement.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/04/2010, 16h28
  2. problème avec commande cut
    Par sajodia dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 03/06/2008, 10h01
  3. Problème avec mon awk
    Par DIE dans le forum Shell et commandes GNU
    Réponses: 0
    Dernier message: 27/12/2007, 09h55
  4. Problème avec commande system(MacOs x)
    Par clampin dans le forum C
    Réponses: 3
    Dernier message: 12/09/2007, 16h06
  5. Probléme avec commande service
    Par rach20032 dans le forum Réseau
    Réponses: 10
    Dernier message: 11/07/2007, 13h03

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