Le Lundi 21 Octobre 2002 23:51, vous avez �crit :
> On Mon, 21 Oct 2002 14:44:07 +0200
> Bernard Lambey <[EMAIL PROTECTED]> wrote:
> 
> ~~~~~~~~~~~~~~~~~~~~
> > Jipe! quand je parlais d'exemples l'autre jour... Dis? Ne 
pourrais-tu
> > nous rendre le service de commenter longuement, largement et...
> > en travers ce programme bash. Je crois que tu ferais grand plaisir
> > � ceux qui, comme moi, essaient de comprendre qqchose au bash...
> > Merci
> > Bernard L.
> > -- 
> 
> pourquoi pas ?
> par contre, permets moi de changer le titre du fil... bash contre 
perl ? surtout pas. non seulement pour ne pas r�veiller tous les 
trolls de la montagne, mais aussi parce que �a n'a pas lieu d'�tre... 
ni contre python ou ruby. et puis le script en question est un peu 
une r�invention du fil � couper le beurre. juste un d�fi amusant � 
relever.
> 
> donc voici la b�te:
> 
> #!/bin/bash
> 
> IFS=$(echo -e "\r")
> 
> i=$(cat $1)
> a=0
> 
> while [ $a -lt ${#i} ]
>       do
>               b=${i:$a:1}
>               case ${i:$a:8} in
>                       \<[aA]\ [hH][rR][eE][fF]=)
>                               echo -n "${i:$a:8}"
>                               a=$((a+8))
>                               while true
>                                       do
>                                               b=${i:$a:1}
>                                               case $b in
>                                                       \>)
>                                                               echo -n "$b"
>                                                               a=$((a+1))
>                                                               break
>                                                               ;;
>                                                       [A-Z])
>                                                               echo -n "$b" | tr 
>[:upper:] [:lower:]
>                                                               a=$((a+1))
>                                                               ;;
>                                                       *)
>                                                               echo -n "$b"
>                                                               a=$((a+1))
>                                                               ;;
>                                               esac
>                                       done
>                               ;;
>                       *)
>                               echo -n "$b"
>                               a=$((a+1))
>                               ;;
>               esac
>               
>       done
> 
> echo
> 
> qu'est-il sens� faire ?
> 
> rechercher dans un fichier html les balises <a href="   "> quelle 
que soit la casse de a href et changer les majuscules en minuscules 
apr�s le = � l'int�rieur de ces balises.
> 
> tout d'abord la base du script.
> 
> il s'agit du script suivant que je vais d'abord analyser:
> 
> #!/bin/bash
> 
> IFS=$(echo -e "\r")
> 
> i=$(cat $1)
> a=0
> 
> while [ $a -lt ${#i} ]
>       do
>               b=${i:$a:1}
>               echo -n "$b"
>               a=$((a+1))
>       done
> 
> echo
> 
> la 1�re ligne "#!/bin/bash" est appel�e shebang pour shell et bang 
qui d�signe le "!". elle permet, lorsque le script est invoqu� par 
son nom, d'appeler l'interpr�teur qui va bien. dans ce cas, le script 
doit �tre ex�cutable. on peut s'en passer et appeler le script en 
argument de l'interpr�teur: "/bin/bash script". dans ce cas, le 
script n'a pas besoin d'�tre ex�cutable. 
> 
> la variable $IFS est par convention le s�parateur de champ interne. 
elle permet de d�finir le ou les s�parateur de champ pour la suite du 
script.
> dans le cas pr�sent, le s�parateur de champ sera le retour 
charriot. ce qui permet d'inclure dans la variable $i, � la ligne 
suivante, le tabulations et sauts de ligne rencontr�es par la 
commande cat $1. elles �quivaudront � un caract�re.
> 
> la 3�me ligne d�finit la variable $i. celle ci contient donc le 
r�sultat de la commande "cat $1". $1 est le 1er argument fourni � 
l'�vocation du script. tout fichier text devrait faire l'affaire.
> 
> la 4�me ligne d�finit � 0 la variable $a qui a son utilit� dans la 
boucle while qui suit.
> 
> la boucle while donc. de la forme while condition; do commande; 
done. ou, pour les non anglophones, tant que condition; faire 
commande; fait.
> 
> la condition:[ $a -lt ${#i} ]
> ${#i} correspond � la longueur de la chaine de caract�res contenue 
dans $i. la boucle ne s'arr�tera que lorsque $a sera �gale � ${#i}.
> 
> 1�re commande: b=${i:$a:1}
> petite digression... d�finissons $toto
> $ toto=abcdefghijklmnopqrstuvwxyz
> quelle est la longueur de $toto ?
> $ echo ${#toto}
> 26
> d�coupons $toto � partir du 20�me caract�re exclus, jusqu'� la fin
> $ echo ${toto:20}
> uvwxyz
> d�coupons 7 caract�res � partir du 3�me inclus
> $ echo ${toto:2:7}
> cdefghi
> donc b=${i:$a:1} va d�finir $b comme contenant une chaine de 
caract�res partant de $a, au d�part 0, donc le 1er caract�re de $i et 
de 1 caract�re. $a �tant indent� par la suite.
> 
> 2�me commande: echo -n "$b"
> $b est affich� dans le terminal, ou dans un fichier si la sortie du 
script est redirig�e vers un fichier avec > fichier.
> -n supprime le saut de ligne que rajoute normalement echo.
> 
> 3�me commande: a=$((a+1)) 
> autre digression... bash permet des op�rations alg�briques simples 
avec des nombres entiers.
> $ echo $((2+3))
> 5
> $ echo $((2*3))
> 6
> $ echo $((2/3))
> 0 <- attention! le r�sultat est un entier. donc valeur enti�re par 
d�faut.
> $ echo $((2-3))
> -1 <- et l�, un entier n�gatif.
> $ echo $((2**3))
> 8
> etc...
> on peut utiliser des "()" comme dans toute expression alg�brique
> $ echo $((3-(2-1)))
> 2
> $ echo $(((3-1)*6+(2+2)**2))
> 28
> donc $a, qui valait 0 au d�part, vaudra a+1 pour la boucle 
suivante. ce qui signifie qu'a chaque boucle, $b va se d�placer dans 
la chaine $i de 1 caract�re, exactement comme un curseur...
> 
> l'avant derni�re ligne "done", signifie la fin de la boucle, et la 
derni�re "echo", permet seulement le retour � un prompt situ� en 
d�but de ligne � la fin du script et non en bout de la ligne 
pr�c�dente.
> 
> maintenant que peut-on en faire ?
> 
> dans le script de d�part, je cherche � trouver une chaine "<a 
href=" quelle que soit la casse. je la fais chercher par un "case".
>  
>       case ${i:$a:8} in
>               \<[aA]\ [hH][rR][eE][fF]=)
> 
> le curseur $b se d�place dans $i en fonction de la valeur de $a. je 
rappelle que b=${i:$a:1}. si les 8 caract�res � partir de $b, cad 
${i:$a:8} (tout le monde suit?) correspondent � cette recherche, 
mat�rialis�e par la ligne se terminant par ")", o� le "\" prot�ge le 
"<" et l'espace d'une interpr�tation erron�e, et [aA] signifie a ou A 
et ainsi de suite..., les actions suivantes vont �tre entreprises.
> 
>               echo -n "${i:$a:8}"
>               a=$((a+8))
> 
> les 8 caract�res � partir de $b vont �tre envoy�e vers la sortie, 
�cran ou fichier et $a est augment�e de +8. le curseur $b se d�place 
donc de 8 caract�res vers la droite.
> 
> ensuite vient une autre boucle while toujours vraie "true", qui va 
d�placer le curseur $b jusqu'a la fin de la balise ">" et changer les 
majuscules en minuscules au passage.
> 
> while true
>       do
>               b=${i:$a:1}
> # le curseur se d�place de 1 caract�re vers la droite
>               case $b in
>                       \>)
>                               echo -n "$b"
>                               a=$((a+1))
>                               break
>                               ;;
> # si le signe ">" est rencontr�, la boucle while est rompue avec 
break
>                       [A-Z])
>                               echo -n "$b" | tr [:upper:] [:lower:]
>                               a=$((a+1))
>                               ;;
> # si un caract�re majuscule est rencontr�, il est tranform� en 
minuscule grace � tr
>                       *)
>                               echo -n "$b"
>                               a=$((a+1))
>                               ;;
> # dans les autres cas, rien de sp�cial ne se passe 
>               esac
>       done
> 
> � chaque fois, bien sur, $a est augment� de 1 pour d�placer le 
curseur et le r�sultat envoy� vers la sortie, �cran ou fichier.
> 
> dans le 1er cas, donc, des actions ont �t� d�finies si les 8 
caract�res qui suivent le curseur correspondent au motif de la 
recherche. actions contenues dans une boucle while et un case. il 
faut bien ensuite d�finir ce qui se passe, s'ils ne correspondent 
pas! c'est le 2�me cas...
> 
>       *)
>               echo -n "$b"
>               a=$((a+1))
>               ;;
> 
> le * signifie "n'importe quoi" ou plut�t "dans tous les autres 
cas". c'est forc�ment le dernier motif de recherche, lorsque tous les 
cas particuliers ont �t� recherch�s. donc dans tous les autres cas, 
on envoye $b vers la sortie, et on augmente $a de 1 pour d�placer le 
curseur.
> 
> voil�! on peut faire plein d'autres choses. du plus simple, comme 
compter le nombre de fois o� apparaissent les noms des doctes Nanard, 
Ismael ou Didier dans un fichier, ou de plus compliqu�es comme leur 
adjoindre une balise <I> </I> ainsi qu'un nombre de 1 � 3 en fonction 
du 1er rencontr�, puis du 2�me, puis du 3�me et qui leur soit propre 
tout au long du fichier et permette de renvoyer � un commentaire en 
fin de page concernant leur vie, leur oeuvre et leurs travers 
secrets...
> 
> en esp�rant avoir r�pondu � votre demande!
> bye
> jipe

Merci jipe !!
-- 
a+
al@in


Vous souhaitez acquerir votre Pack ou des Services MandrakeSoft?
Rendez-vous sur "http://www.mandrakestore.com";

Répondre à