Forum Programmation.perl Besoin d'aide pour mon premier script en perl: parser un fichier BIND

Posté par  . Licence CC By‑SA.
Étiquettes :
0
7
juil.
2015

Bonjour à tous,

Je suis tout nouveau en perl et je viens du monde ms.
Ne connaissant que vbs et powershell il faudra être patient avec moi.

Bon voilà mon besoins:
Je dois faire des modifications massive d'enregistrements DNS dans 15 zones Bind9.7.
En entrée j'ai un fichier csv qui se compose ainsi.
RecordName,Type,NewIP
SERVER1,A,YYYY
server2,A,YYYY

L'idée algorithmique serait la suivante:

#------debut script ------------------
    $csvfile = readcsv(/tmp/csv)
    $zonefile = open (/var/cache/bind/mydomain.com)

    foreach ($row in $csvfile)
    {
      $RowMemberTab = split ($row,[,]) /* split la ligne dans un tableau ,separateur = , */

        foreach ($record in $zonefile)
        {
         $recordMemberTab = split ($record, [blank space]) /* Split la ligne dans un tableau          séparateur = espace blanc */ 

           if $recordMemberTab(1) match $RowMemberTab(1)
            {
            print ( ";" + $record -> $zonefile) /* duplique la ligne en insérant ; en debut de ligne)
            delete ( $record -> $zonefile) /* supprime la ligne */
            print  $RowMemberTab(1) + \t + $RowMemberTab(2) + $RowMemberTab(3) -> $zonefile 
            /* ecrit une nouvelle ligne avec les infos du csv et separateur tabulation */
            }
            else 
            {
             print (  $RowMemberTab(1) + \t + $RowMemberTab(2) + $RowMemberTab(3) -> $zonefile )
            }
         next 
        }
    }
    $zonefile.write()
    $zonefile.close()
#---------- fin script -------------------

Mais je ne sais pas la traduire en perl.
Un coup de main serait le bien venu

Merci par avance de votre aide
0rwell

  • # shell

    Posté par  (site web personnel, Mastodon) . Évalué à 3. Dernière modification le 08 juillet 2015 à 13:44.

    Salut, je connais pas perl mais en shell je ferais un truc comme ça :

    #!/bin/sh
    csv="/tmp/csvfile"
    zone="/var/xxx"
    
    for line in `cat $csv`
    do
       recordname=`echo $line | cut -d';' -f1`
       type=`echo $line | cut -d';' -f2`
       ip=`echo $line | cut -d';' -f3`
    
       sed "s/$recordname/;$recordname/" -i $zone
       echo $recordname '\t' $type $ip >> $zone
    done

    (fait en live, pas réfléchi, pas testé. Faudrait au moins limiter le sed pour pas pas qu'il rajoute des ; sur les lignes déjà commentées)

    • [^] # Re: shell

      Posté par  (site web personnel) . Évalué à 2.

      Tu peux faire beaucoup plus simple pour la lecture en faisant

      process_lines()
      {
        local recordname type ip
        while IFS=',' read recordname type ip
          # Do something with the zone file
        done
      }
      
      print_csv()
      {
        sed -n -e '2,$p' "$1"
      }
      
      print_csv "/tm[/csvfile" | process_lines
      
      • [^] # Re: shell

        Posté par  . Évalué à 1.

        Merci beaucoup Michaël.
        Je suis un peu plus séduit par la solution sans fonction de Matthieu me parait( pour moi seulement) plus facile à creuser compte tenu de mon niveau faible en scripting bash.

    • [^] # Re: shell

      Posté par  . Évalué à 1.

      Merci beaucoup Mathieu.

      Je vais essayer de creuser à partir de ton bloc de code.

  • # En AWK

    Posté par  . Évalué à 3.

    Pour ce que je comprends, sortir Perl pour ça est un peu overkill. Un essai en AWK qui devrait te donner ce que je conçois être le résultat final (/tmp/csv dans le même ordre mais avec les entrées présentes dans mydomain.com précédées d'un ";", puis le contenu de mydomain.com avec par ligne une tabulation séparant le premier champ initial de la concaténation des deux autres) :

    (FNR == NR) {
        split($0, t, ",")
        CSV[t[1]] # La clé de contrôle
        LINE[C++] = t[1]"\t"t[2]t[3]
        next
    }   
    ($1 in CSV) { printf("%s", ";") }
    { print }
    END {
        for (i=0; i<C; i++)
            print LINE[i]     
    }

    Pour exécuter, il suffit de lancer : awk -f ce_script.awk mydomain.com /tmp/csv. Le résultat sera envoyé sur la sortie standard que tu pourras rediriger vers n'importe quel fichier (plus prudent àmha que de bosser directement sur la base initiale).

    Bien sûr, je n'ai pas testé plus que ça, et si tu n'es pas attaché à l'ordre des lignes, on peut optimiser. ;)

    • [^] # Re: En AWK

      Posté par  . Évalué à 1.

      Bonjour MrSpackMan

      Merci beaucoup pour ta proposition.

      Je vais essayer ta solution bien que je ne comprends pas bien le code que tu me proposes.

      Éventuellement si je peux abuser peux tu le commenter pour mon information/formation?
      Autant je comprends bien les scripts proposés par Matthieu et Michael autant le tiens dépasse un peu ma compréhension.
      Je viens du monde windows et j'ai un peu plus l'habitude des langages objets comme vbs ou powershell.
      A ma connaissance à part les implémentations des outils Unix pour windows les expressions régulières ne sont pas choses courantes dans le monde windows.

      • [^] # Re: En AWK

        Posté par  . Évalué à 2.

        En fait il n'y a aucune expression régulière dans ce code. :)

        FNR et NR correspondent respectivement au nombre de lignes (on parle d'enregistrements en fait, car en changeant la valeur de RS, on peut acquérir un fichier en d'autres portions qu'en lignes) lues dans le fichier traité et dans l'ensemble des fichiers. Ici ça sert à traiter séparément le premier fichier "mydomain" (d'où le next en fin le bloc) : je découpe chaque ligne dans le tableau t en prenant la virgule comme séparation de champ, j'enregistre le premier champ comme clé dans le hash CSV, puis la ligne dans son aspect définitif comme valeur dans LINE.

        Le deuxième bloc va donc traiter le fichier "cvs". Il prend chaque premier champ et vérifie si celui-ci est une clé dans CVS. Si c'est le cas il émet un point-virgule. Ensuite et dans tous les cas, il imprime la ligne.

        Le dernier bloc END est spécial et exécuté en fin de traitement. Ici il restaure le contenu de LINE, c'est à dire le contenu de "mydomain" formaté comme il se doit.

        Si tu veux en apprendre plus sur AWK, qui a été une grande source d'inspiration pour Perl, je te conseille le Manuel de l'implémentation GNU, très complet, et la page POSIX, qui fera une bonne référence pour la programmation quotidienne. Si tu comptes te lancer dans la programmation shell, apprendre AWK est vraiment un bon investissement qui permet de coder rapidement des petits filtres sur mesure très efficaces.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.