Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1860 connectés 

  FORUM HardWare.fr
  Programmation
  Shell/Batch

  script shell + awk

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

script shell + awk

n°2005642
Spyant
Posté le 29-06-2010 à 12:18:31  profilanswer
 

Bonjour, ça fait plusieurs que je me casse la tête sur un truc apparemment tout bête.  
 
En fait j'ai deux fichiers textes et je voudrais récupérer les informations qui sont sur le premier (des hostname, adresse Ip et MAC) pour les utiliser dans l'écriture de la base d'adresses fixes de mon serveur dhcp.  
 
Alors j'ai pensé à faire un script avedc awk, mais je galère vraiment à comprendre comment ça marche awk  :sweat:  
 
J'ai essayé plusieurs trucs dont aucun ne marche:  
 
1) un seul script avec awk qui écrit dans le fichier cible.  
 
2) un script awk qui renvoit les infos de la lignes en paramètres ds le script shell.  
 
je vous met la deuxième idée pour l'instant:
 

Citation :

awk 'BEGIN  
 
{
  while (NR < 31)
  do
    {./dhcp.sh  $1 $2 $3}'
 ./dhcp_44.txt


 
[quote= le dhcp.sh]#!/bin/bash
 
if [ $3 -ge 130 ] && [ $3 -le 224 ]  
 then echo "host $1" { >> dhcp.txt
  echo "hardware ethernet $2;" >> dhcp.txt
  echo "fixed-address 134.157.44.$3;" >> dhcp.txt
    echo "option host-name "'"'$1'"'";" >> dhcp.txt
    echo '}' >> dhcp.txt
    echo>> dhcp.txt
else echo Adresse hors de la plage
fi[/quote]
 
 
Alors v'la, quelques questions parceque vraiment je galère à comprendre les tutos sur awk (je sais pas pourquoi).  
 
comment on fait pour rendre un fichier awk executable ? et sinon pour l'appeler dans un script ?  
 
 
Comme vous le voyez je suis un stagiaire débutant héhé  :p


Message édité par Spyant le 29-06-2010 à 15:24:59
mood
Publicité
Posté le 29-06-2010 à 12:18:31  profilanswer
 

n°2005965
aigles
Posté le 30-06-2010 à 10:47:38  profilanswer
 

  • Rapidement quelques infos sur awk (le minimum du minimum du minimum) :


Un programme awk est contitué d'une suite de paires :

Code :
  1. pattern { action }


Le pattern permet de sélectionner des lignes en entrée, pour chacune de ces ligne selectionnée le code action est exécuté.
Si le pattern n'est pas sélectionnè, action s'applique à toutes les lignes d'entrée.
Si l'action n'est pas spécifiée, les lignes sélectionnées sont écrites en sortie.
 
La ligne entière est dans $0, elle est décomposées en fonction du séparateur (FS) en différents les champs sont $1, $2...
 

  • Ton problème:


D'après ce que tu as indiqué (texte et code), les lignes en entrées contiennent 3 champs (je suppose spérarés par des espaces).
Nous aurons donc dans le programme awk :
   $0 = Ligne lue
   $1 = hostname
   $2 = adresse MAC
   $3 = adresse IP
   
Seules les lignes comportant une adresse IP entre 130 et 224 compris, le pattern est donc :

Code :
  1. $3 >= 130 && $3 <= 224


 
Pour chaque ligne sélectionnée, la partie action va consister à afficher les données pour le fichier dfhct, soit :
 

Code :
  1. printf "host %s {\n", $1;
  2. printf "hardware ethernet %s;\n", $2;
  3. printf "fixed-address 134.157.44.%3;\n", $3;
  4. printf "option host-name %s%s%s;\n", $1
  5. print  "}\n"


La variable Q va être défini avec la valeur simple quote qui est toujours un peu délicate à utiliser dans un programme awk inclus dans un shell.
 
Au final, nous obtenons le script shell :

Code :
  1. #!/usr/bin/bash
  2. awk '
  3. $3 >= 130 && $3 <= 224 {
  4.    printf "host %s {\n", $1;
  5.    printf "hardware ethernet %s;\n", $2;
  6.    printf "fixed-address 134.157.44.%3;\n", $3;
  7.    printf "option host-name %s%s%s;\n", Q, $1, Q;
  8.    print  "}\n";
  9. }
  10. ' Q="'" ./dhcp_44.txt > ./dhcp.txt


 
Je n'ai pas très bien compris ce que tu veux faire avec la boucle while, il semble que tu veux te limiter au 30 premières lignes du fichier d'entréee.
Si c'est la cas  il suffit de modifier le pattern (NR est le numéro de ligne en entrée) :

Code :
  1. NR<=30 && $3 >= 130 && $3 <= 224


Une autre solution est d'ajouter un couple pattern/action qui arrête le traitement dés la 31eme ligne :

Code :
  1. #!/usr/bin/bash
  2. awk '
  3. NR>30 {
  4.    exit;
  5. }
  6. $3 >= 130 && $3 <= 224 {
  7.    printf "host %s {\n", $1;
  8.    printf "hardware ethernet %s;\n", $2;
  9.    printf "fixed-address 134.157.44.%3;\n", $3;
  10.    printf "option host-name %s%s%s;\n", Q, $1, Q;
  11.    print  "}\n";
  12. }
  13. ' Q="'" ./dhcp_44.txt > ./dhcp.txt


 
 
Jean-Pierre.

n°2006062
Spyant
Posté le 30-06-2010 à 15:18:41  profilanswer
 

Merci beaucoup jean-pierre, en fait avec la boucle while, ben j'essayais de faire boucler awk mais j'avais pas compris que awk boucle implicitement (ce qui est bien pratique d'ailleurs).  
 
J'avais pas du tout compris l'histoire des patterns non plus; Mais du coup, quel est l'interêt des "if" alors dans awk ??  
 
J'avais quand même avancé mais sans la boucle de contrôle de $3. Ca donnait ça:
 

Citation :

awk '{print "host " $1" {" };  
     {print "hardware ethernet"$2"";""};
     {print "fixed-address 134.157.44."$3";"};
     {print "option host-name \"" $1 "\";"};
     {print "'}'\n\n"};
     
' dhcp_44.txt >> dhcp.txt


 
Ton script marche au poil (sauf que c'est des " que j'ai besoin et que ça marche pas non plus avec Q, mais j'ai trouvé une parade héhé ...).
 
Mais il me fait le même truc bizarre que le mien : après $3, il saute automatiquement une ligne mettant le ";" à la ligne du dessous ... et je comprends pas pourquoi alors qu'il ne le fait ni pour la ligne d'en-dessous ni pour celle du dessus.
 
J'ai même essayé de mettre le ";" dans une variable Q et de la rajouter à la fin et ... il saute quand même une ligne  :heink:  
 
Sinon, pour aller au-delà du "minimum du minimum du minimum" tu n'aurais pas un livre à me conseiller ? Parceque après 3 jours à chercher sur le net, j'ai pas trouver de cours vraiment complet sur awk et ses options :pt1cable:  
 
En tout cas, merci bien sensei  :jap:


Message édité par Spyant le 30-06-2010 à 15:24:11
n°2006136
aigles
Posté le 30-06-2010 à 17:26:34  profilanswer
 

La documentation de gawk "Effective AWK Programming - A User's Guide for GNU Awk" est très bien faite et très complète :  
http://polymer.bu.edu/~fding/awk/gawk_toc.html
Il y a aussi le bouquin "sed & awk" de chez O"REILLY :  
http://docstore.mik.ua/orelly/unix/sedawk/index.htm
 
Les deux sont en anglais, il doit exister des traductions mais je n'ai pas les liens.
 
 
Concernant le programme, voici la version avec doubles-quottes :

Code :
  1. #!/usr/bin/bash
  2. awk '
  3. $3 >= 130 && $3 <= 224 {
  4.    printf "host %s {\n", $1;
  5.    printf "hardware ethernet %s;\n", $2;
  6.    printf "fixed-address 134.157.44.%3;\n", $3;
  7.    printf "option host-name \"%s\";\n", $1;
  8.    print  "}\n";
  9. }
  10.   10. '  ./dhcp_44.txt > ./dhcp.txt


 
Il semble que ton fichier en entrée soit au format DOS c'est à dire avec <cr><lf> comme séparateur de ligne au lieu de <lf> pour le format Unix.
Première solution, convertir ton fichier avec dos2unix par exemple.
Deuxième solution, adapter le programme awk :

Code :
  1. $3 >= 130 && $3 <= 224 {
  2.    sub(/\r$/, "" );
  3.    printf "host %s {\n", $1;


 
Jean-Pierre.

n°2006140
Spyant
Posté le 30-06-2010 à 17:43:06  profilanswer
 

Effectivement le fichier "dhcp_44" a été fait sous win. Comme moi je l'utilise jamais, j'avais même pas pensé à ce genre de problème là lol.
 
Et c'est ça qui fait que mon point virgule il saute à la ligne dd=u dessous systématiquement ?  
 
Je vais plutôt essayer la deuxième solution parcqu'il faut que ça reste utilisable après moi.  
 
En tout cas merci, et je pense que je vais aller m'acheter le O'Reilly, en général j'aime bien leur livres.

n°2012922
mic_12
Posté le 29-07-2010 à 14:43:02  profilanswer
 

salut,
 
je me permet d'utiliser ce sujet car j'ai également un souci avec awk et une boucle.
 

Citation :

cat fichier1 | while read
 do  
 i=$(($i+1))
 echo $i
 awk 'NR==$i {print NR " : " $1}' fichier1
 done


ce que je veux, c'est lire le fichier et pour chaque ligne récupérer le champ $1. A terme, je compte rajouter un awk d'un fichier2 pour lire le même numéro de ligne (d'où la boucle et le compteur) mais déjà là ca marche pas :D Pour le numéro de ligne, si je mets un chiffre c'est ok mais si je mets une variable ca marche pas. Il y a une astuce ? :)


---------------
Site photo
n°2012975
mic_12
Posté le 29-07-2010 à 17:18:02  profilanswer
 

personne s'il vous plait ? :) Je suis complètement bloqué :(


---------------
Site photo
n°2013283
Sve@r
Posté le 30-07-2010 à 19:16:30  profilanswer
 

mic_12 a écrit :

personne s'il vous plait ? :) Je suis complètement bloqué :(


Parce qu'on ne squatte pas les topics des autres. Ouvre-toi le tien.
 
Mais bon, maintenant qu'on y est... Alors la syntaxe "$i" est une syntaxe shell. Dans un script awk, elle a une tout autre signification. Normal donc que demander "$i" dans un script awk avec l'idée de variable shell ne fonctionne pas !!!
 

Code :
  1. cat fichier1 | while read lig
  2. do  
  3. i=$(($i+1))
  4. echo $i
  5. awk -vcible=$i 'NR==cible {print NR " : " $1}' fichier1
  6. done


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Shell/Batch

  script shell + awk

 

Sujets relatifs
script shell bashexecuter un script shell dans une page web
Lancer un script shell (ksh) si une requete retourne une valeurutilisation awk dans un script shell
Programmation script shell ksh unixPrendre la valeur après un ping
script shellShell : besoin d'aide pour mon script
Exécuter un script SHELL grace au CGIScript shell pour récupèrer des images sur une camera
Plus de sujets relatifs à : script shell + awk


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR