aide pous script bash

Forum dédié à la distribution du même nom et que vous pourrez télécharger sur http://www.contribs.org. La nouvelle version de cette distribution se nomme SME Server

Modérateur: modos Ixus

aide pous script bash

Messagepar ecureuil1 » 30 Sep 2005 18:54

Bonjour,

Je suis en train de faire un script pour faire du publipostage avec une imprimante samba via le poste client

Je veux lire un fichier qui contient un certain nombre de paramètres
Pour l'instant, j'en ai mis 2.

Le premier correspond à un numéro de tél, le deuxième à un nom
Le premier est obligatoire, le deuxième est facultatif
Comme séparateur de champ, j'ai mis '|'

fichier :
1|
0|titi
2|tutu

Le 2ème champ du 1ère enreg est à blanc

code :
#!/bin/sh
...
NBRLIST=(`awk -F\| '{nblst=$1; gsub(/\n/," ",nblst); printf ("%s ", nblst) }' ${FAXLIST}` )
NAMEDEST=(`awk -F\| '{nblst=$2; gsub(/\n/," ",nblst); printf ("%s ", nblst) }' ${FAXLIST}` )
...
echo "Nombre de fax à envoyer : ${#NBRLIST[@]}"
echo "liste des numéros ${NBRLIST[@]}--"
echo "liste des noms ${NAMEDEST[@]}--"
echo "Nombre de noms --${#NAMEDEST[@]}--"
nj=0
mj=0
for j in ${NBRLIST[@]}
do
let nj=$nj+1
echo " poste $nj : tél ${j} nom ${NAMEDEST[$mj]} "
let mj=$mj+1
done



Résultat :
Nombre de fax à envoyer : 3
liste des numéros 1 0 2--
liste des noms titi tutu--
Nombre de noms --2--
...
poste 1 : tél 1 nom titi
poste 2 : tél 0 nom tutu
poste 3 : tél 2 nom

J'aimerai avoir :
poste 1 : tél 1 nom
poste 2 : tél 0 nom titi
poste 3 : tél 2 nom tutu

Vous n'auriez pas une idée?

anne
ecureuil
Avatar de l’utilisateur
ecureuil1
Contre-Amiral
Contre-Amiral
 
Messages: 448
Inscrit le: 04 Avr 2002 00:00
Localisation: Grenoble, France

Messagepar sibsib » 30 Sep 2005 22:19

Salut, Anne,

Il t'en font voir de toutes les couleurs, tes fax :-)

j'eu écrit :

Code: Tout sélectionner
cat ${FAXLIST} | awk '
BEGIN { FS = "|" ; poste=1 }
        { printf "poste %2d : tel %10d nom %s\n", poste, $1, $2 ;
          poste++ }
'


A+,
Pascal
Sibsib, admin heureux d'un petit SME !!!
- SME 8.0 beta 6 dans une VM :-)
- ESXI 4.1 sur hardware noname
Ma petite page sur SME
Avatar de l’utilisateur
sibsib
Amiral
Amiral
 
Messages: 2368
Inscrit le: 11 Mai 2002 00:00
Localisation: France - région parisienne

Messagepar ecureuil1 » 30 Sep 2005 22:55

sibsib a écrit:Salut, Anne,

Il t'en font voir de toutes les couleurs, tes fax :-)

peuh... on se moque :-({|=

j'eu écrit :

Code: Tout sélectionner
cat ${FAXLIST} | awk '
BEGIN { FS = "|" ; poste=1 }
        { printf "poste %2d : tel %10d nom %s\n", poste, $1, $2 ;
          poste++ }
'


A+,
Pascal


Pour le code ce n'est pas pour imprimer... l'impression c'était pour voir ce qui se passer...
Je veux mettre cela dans un tableau pour ne pas avoir à relire le fichier chaque fois que je fais un traitement!...

Je lis chaque poste du tableau des numéros de fax et j'envoie le fax avec le n° récupéré... L'enregistrement que je lis peut avoir plusieurs champ... nom de l'expéditeur, nom du destinataire...Seul le n° de téléphone est obligatoire...

En plus, je ne conanaissais pas awk, ce n'est pas très rapide!

Question subsidiaire en bash
---------------------------------

#!/bin/sh
...
# read file for multicast
if [ "${FAXNUMTOS}" != "" ] ; then
i=0
cat ${FAXLIST} | while read line # read file line by line
do
NBRLIST[$i]=`echo $line | cut -d"|" -f1 ` # extract numéro fax destinataire (obligatoire)
NAMEDEST[$i]=`echo $line | cut -d"|" -f2 ` # nom destinataire (facultatif)
i=$(($i+1))
echo $i
echo ${NBRLIST[@]}
done
echo "--$i--"
i=$(($i-1))
echo "--${i}--"
echo "--${NBRLIST[@]}--"
fi
...
résultat :
+ i=0
+ cat /tmp/listfax
+ read line
++ echo '123456||'
++ cut '-d|' -f1
+ NBRLIST[$i]=123456
++ echo '123456||'
++ cut '-d|' -f2
+ NAMEDEST[$i]=
+ i=1
+ echo 1
1
+ echo 123456
123456
+ read line
++ echo '987654321|titi|'
++ cut '-d|' -f1
+ NBRLIST[$i]=987654321
++ echo '987654321|titi|'
++ cut '-d|' -f2
+ NAMEDEST[$i]=titi
+ i=2
+ echo 2
2
+ echo 123456 987654321
123456 987654321
+ read line
+ echo --0--
--0--
+ i=-1
+ echo ---1--
---1--
+ echo ----
----

Quand je sors de la boucle, y-a plus rien dans le tabeau et dans la variable i

Si vous pouviez m'expliquer l'erreur!

Je crois que je vais passer en perl!

anne
ecureuil
Avatar de l’utilisateur
ecureuil1
Contre-Amiral
Contre-Amiral
 
Messages: 448
Inscrit le: 04 Avr 2002 00:00
Localisation: Grenoble, France

Messagepar jdh » 01 Oct 2005 00:27

Je pense (pour avoir testé à de multiples reprises) que "awk" est bien plus rapide que "bash". Sans compter la concision du code !

Avec "bash", on utilise force de "cut -f" pour séparer les champs, alors que sous "awk", on précise le séparateur de champ (FS), puis à chaque ligne $1, $2, ... contiennent automatiquement le champ1, champ 2, ...

Si tu veux executer une commande, il suffit de remplacer "printf" par une instruction "exec".


Moins puissant que Perl, mais bien plus rapide à apprendre, "awk" est très pratique quand il s'agit de traiter des fichiers présentant ce genre de régularité.


Concernant le script bash que tu fournis en 2me, je ne vois pas ce que tu cherches. Si tu pars d'un fichier "liste", c'est normalement pour executer une action sur chaque ligne. Dans ce cadre pourquoi stocker quoi que ce soit ? Une boucle de lecture (cat fic | while read p1 p2 p3; do ... done) et on traite chaque ligne facilement. Par ailleurs le shell n'est pas vraiment fait pour créer des variables qui passe d'un script à l'autre (même avec export).
Avatar de l’utilisateur
jdh
Amiral
Amiral
 
Messages: 4741
Inscrit le: 29 Déc 2002 01:00
Localisation: Nantes

Messagepar ecureuil1 » 01 Oct 2005 05:54

recoucou,

code suivant :

-----------------------------------------------------------------------------------
#!/bin/sh

#set -x

traitement()
{
echo "---------------------------"
echo
echo "fichier ${FAXLIST} "
echo
echo "`cat ${FAXLIST}`"
echo

LISTFAX=( `cat "${FAXLIST}"` )
echo "LISTFAX: "${LISTFAX[@]}
echo
max=${#LISTFAX[@]}
i=0
while [ $i -lt $max ]
do
echo "LISTFAX[$i]: "${LISTFAX[i]}
numfax=`echo ${LISTFAX[i]} | cut -d"|" -f1`
nomfax=`echo ${LISTFAX[i]} | cut -d"|" -f2`
NBRLIST[i]=$numfax
NAMEDEST[i]=$nomfax
let "i += 1"
done

echo
echo "Nombre de fax à envoyer : ${#NBRLIST[@]}"
echo "Nombre de noms --${#NAMEDEST[@]}--"
echo

nj=1
mj=0
while [ $nj -lt 5 ]
do
echo " poste $nj : tél --${NBRLIST[$mj]}-- nom --${NAMEDEST[$mj]}-- "
let nj=$nj+1
let mj=$mj+1
done

echo "---------------------------"
echo
}

traitement1()
{
echo "fichier ${FAXLIST} "
echo
echo "`cat ${FAXLIST}`"

NBRLIST=(`awk -F\| '{printf("\"%s\"\n",$1);}' ${FAXLIST}`)
NAMEDEST=(`awk -F\| '{printf("\"%s\"\n",$2);}' ${FAXLIST}`)

echo "Nombre de fax à envoyer : ${#NBRLIST[@]}"
echo "Nombre de noms --${#NAMEDEST[@]}--"
echo

nj=1
mj=0
while [ $nj -lt 5 ]
do
echo " poste $nj : tél --${NBRLIST[$mj]}-- nom --${NAMEDEST[$mj]}-- "
let nj=$nj+1
let mj=$mj+1
done

echo "---------------------------"
echo
}

IFS=$'\n'

FAXLIST=/tmp/listfax
traitement

FAXLIST=/tmp/mistfax
traitement

FAXLIST=/tmp/listfax
traitement1

FAXLIST=/tmp/mistfax
traitement1

-----------------------------------------------------------------------------------

# cat listfax
1||
0|titi z1|
2|tutu|
# cat mistfax
1| |
0|titi|
2|tutu|

Il suffisait de mettre IFS=$'\n'

anne
ecureuil
Avatar de l’utilisateur
ecureuil1
Contre-Amiral
Contre-Amiral
 
Messages: 448
Inscrit le: 04 Avr 2002 00:00
Localisation: Grenoble, France

Messagepar jdh » 01 Oct 2005 09:42

Quelle complication !

Ce que tu veux faire (en regardant la sortie des scripts) ne me semble être finalement qu'une réécriture de chaque ligne avec un n° qui s'incrémente en début de ligne transformée. Pourquoi sortir l'artillerie des tableaux pour faire ce genre de choses.

Code: Tout sélectionner
#!/bin/bash

traitement()
{
echo "---------------------------"
echo
echo "fichier $FAXLIST"
echo
cat $FAXLIST
echo

IFS="|"
max=0
while read num nom fin_de_ligne
do
  max=$[$max + 1]
  echo " poste $max : tel --${num}-- nom --${nom}--"
done <$FAXLIST

echo
echo "nb de lignes : $max"
echo
}

FAXLIST=listfax
traitement

FAXLIST=mistfax
traitement



Quelques remarques :

- le "sha-bang" est #!/bin/bash pour executer le script avec bash (et non sh)
- la syntaxe ${var} s'impose quand les caractères qui suivent "var" sont des lettres (puisque cela ferait une autre variable !)
- IFS est une variable bash qui indique le séparateur d'arguments : s'utilise avec read ou avec set suivi de commande shift
- la syntaxe "while read ; do ... done <fic" est différente de "cat fic | while read ; do ... done" car le while est dans un autre processus dans le 2me cas et les changements de valeurs de variable ne sont pas répercutés (difficile à trouver)

Le script awk de sisib (je ne fais pas mieux) n'est il pas beaucoup plus simple et naturel ?
Awk est un "language" d'une puissance et d'une simplicité tout à fait remarquable.
Ce n'est pas par hasard s'il existe une commande a2p (awk to perl).
Notamment un atout exceptionnel d'awk est l'utilisation de tableau hash, c'est à dire de tableaux avec indices texte, ce qui permet de faire des cumuls par clé par exemple de façon élémentaire.



Tu peux trouver de très bonne docs sur http://www.tldp.org/guides.html (même si c'est en anglais).
Avatar de l’utilisateur
jdh
Amiral
Amiral
 
Messages: 4741
Inscrit le: 29 Déc 2002 01:00
Localisation: Nantes

Messagepar ecureuil1 » 01 Oct 2005 15:49

Je ne veux pas imprimer mais me servir de cette liste plusieurs fois pour faire différentes choses...
Je ne me vois pas relire le fichier x fois dans le pgm...

Je la met donc dans un tableau pour cela!

La cde awk est très concise!
les versions cat et read : y-a un peu plus de lignes!

Je ne sais pas laquelle est la mieux? !!!

Cela me permet aussi d'apprendre le bash!
J'ai bien failli craquer et passer en perl que je maitrise un tt petit peu plus!

anne
ecureuil
Avatar de l’utilisateur
ecureuil1
Contre-Amiral
Contre-Amiral
 
Messages: 448
Inscrit le: 04 Avr 2002 00:00
Localisation: Grenoble, France

Messagepar sibsib » 01 Oct 2005 20:58

Salut Anne et Jdh,

Anne,

Comme te le disait jdh, tu peux très bien avec awk stocker des variables dans un tableau, et lancer pleins de commandes en fonction d'un nombre de paramètres impressionnant, snas jamais relire le fichier.

La commande exec te permet ceci, et il existe un nombre de boucles imbriquées formidable dans awk.

Au niveau perf, mais dans un contexte assez particulier : J'avais un traitement de type shell script qui tournait sous cygwin (Le monde unix porté sous windows, c'est génial : http://www.cygwin.com) sur un serveur NT4.
Ce script trouranit plusieurs fois par minutes en cas de rush (analyse d'évènements réseau 'on the fly'). Le problème (spécifique à Windows) c'est que chaque commande étant un nouveau process, windows utilise énormément de ressources CPU pour lancer un programme. Résultat : le shell script mettait 30 à 45 secondes à c'exécuter. En le remplaçant par un script awk, je suis tombé à 2 secondes :-)
C'est quand même caricatural, car sous Unix, un lancement de process est considérablement moins gourmand (même si chaque commande sollicite pas mal de ressources au démarrage et à l'arret).

Ceci dit, j'ai maintenant complètement abandonné awk, sauf quand je l'utilise pour parser un fichier 'bêtement' : perl est quand même nettement plus puissant, et de plus, nettement plus portable que awk (les versions de awk entre une machine linux et une machine Solaris ... aie aie aie !).

Donc, sans hésiter, je te conseille perl, même si awk semlbe largement répondre à ton besoin pour le moment.

A+,
Pascal
Sibsib, admin heureux d'un petit SME !!!
- SME 8.0 beta 6 dans une VM :-)
- ESXI 4.1 sur hardware noname
Ma petite page sur SME
Avatar de l’utilisateur
sibsib
Amiral
Amiral
 
Messages: 2368
Inscrit le: 11 Mai 2002 00:00
Localisation: France - région parisienne


Retour vers E-Smith / SME Server

Qui est en ligne ?

Utilisateur(s) parcourant actuellement ce forum : Aucun utilisateur inscrit et 1 invité

cron