[zsh] Petit exemple de parsing d'un fichier texte simple
Bonjour à tous, comme vous le savez sans doute, zsh offre de nombreuses fonctions de pattern matching qui permettent - dans des cas relativement simples - de se passer des outils tel que awk, sed, etc.. Je vous propose donc de découvrir ces fonctionnalitées via un petit exemple pratique. Soit le fichier suivant : ,------ /etc/zones/index | # Copyright 2004 Sun Microsystems, Inc. All rights reserved. | # Use is subject to license terms. | # | # ident "@(#)zones-index 1.2 04/04/01 SMI" | # | # DO NOT EDIT: this file is automatically generated by zoneadm(1M) | # and zonecfg(1M). Any manual changes will be lost. | # | global:installed:/ | tools:installed:/zones/tools:00000000-0100-0000-2879-0408fb610508 | databases:installed:/zones/databases:00000000-0100-0000-2879-0408fb610508 | public-ejbca:installed:/zones/public-ejbca:00000000-0100-0000-e078-0408fb610508 | public:installed:/zones/public:00000000-0100-0000-c078-0408fb610508 `--- Mon objectif est d'obtenir la liste des premiers mots des lignes non commentées (c'est à dire global, tools, databases, etc...). Pour y parvenir, j'ai choisi de créer un tableau de lignes, supprimer les lignes qui contiennent # au début, puis supprimer des lignes ce qui suit le premier : comme on l'a vu ce matin, l'utilisation de ("${(f)$(< fichier)}") permet de créer un tableau de lignes à partir du fichier donné. En fait, je rajoute simplement deux substitutions au résultat obtenu. La première est ##\#* qui permet de supprimer tout ce qui suit #* (la variable obtenu par ("${(f)$(< fichier)}") étant déjà un tableau, ca supprime les lignes commentés), notez que # à une signification (1), il faut donc escaper mon caractère #, et comme je veux supprimer toute la ligne, je rajoute *, ce qui donne donc ${name##\#*} La seconde est //:* (2) (sous entendu /:*/) qui permet de supprimer tout ce qui suit :* Ce qui pourrait donc nous donner quelque chose du genre : ,------ | % lines=("${(f)$(< /etc/zones/index)}") | % nocomments=(${lines##\#*}) | % zones=(${nocomments/:*/}) | % echo $zones | global tools databases public-ejbca public `--- Ce qui nous donne en oneliner : ,------ | % zones=(${${(a)"${(f)$(< /etc/zones/index)}"##\#*}/:*}) | % print -a $zones | global tools databases public-ejbca public `--- Et voilà ! pas de fork, rien que du pur zsh, et du français loin d'être pur, lui :) J'espère que cela vous sera utile. Notes (section 13, mais vous commencez à en avoir l'habitude :) 1) ${name#pattern}, ${name##pattern} If the pattern matches the beginning of the value of name, then substitute the value of name with the matched portion deleted; otherwise, just substitute the value of name. In the first form, the smallest matching pattern is preferred; in the second form, the largest matching pattern is preferred. 2) ${name/pattern/repl}, ${name//pattern/repl} Replace the longest possible match of pattern in the expansion of parameter name by string repl. The first form replaces just the first occurrence, the second form all occurrences. -- http://asyd.net/home/ - Home Page http://guses.org/home/ - French Speaking Solaris User Group
Bruno Bonfils wrote:
Notes (section 13, mais vous commencez à en avoir l'habitude :)
1) ${name#pattern}, ${name##pattern}
If the pattern matches the beginning of the value of name, then substitute the value of name with the matched portion deleted; otherwise, just substitute the value of name. In the first form, the smallest matching pattern is preferred; in the second form, the largest matching pattern is preferred.
2) ${name/pattern/repl}, ${name//pattern/repl}
Replace the longest possible match of pattern in the expansion of parameter name by string repl. The first form replaces just the first occurrence, the second form all occurrences.
Pour info, ça marche aussi avec bash ça (pas les tableaux par contre, l'implémentation des tableaux en bash est différente semble-t-il). Il me semble avoir entendu quelqu'un dire que c'était POSIX, mais je ne saurais l'affirmer :) -- Clément Hermann (nodens)
On ven 08 septembre, Clement Hermann wrote:
Pour info, ça marche aussi avec bash ça (pas les tableaux par contre, l'implémentation des tableaux en bash est différente semble-t-il).
Certes, mais par contre ce qui m'ennuie en bash : # var="Salut_nodnes" ; echo ${${var//_/ }//ne/en} bash: ${${var//_/ }//ne/en}: bad substitution évidemment, pas la peine de préciser que... % var="Salut_nodnes" ; echo ${${var//_/ }//ne/en} Salut nodens Du coup, ca devient vite lourd :/ -- http://asyd.net/home/ - Home Page http://guses.org/home/ - French Speaking Solaris User Group
le 08/09/2006, Bruno Bonfils nous �crivait :
Certes, mais par contre ce qui m'ennuie en bash :
# var="Salut_nodnes" ; echo ${${var//_/ }//ne/en} bash: ${${var//_/ }//ne/en}: bad substitution
évidemment, pas la peine de préciser que...
% var="Salut_nodnes" ; echo ${${var//_/ }//ne/en} Salut nodens
Du coup, ca devient vite lourd :/
et zsh vite illisible quand on abuse des nested (cf. les scripts de completion fournis dans la distrib standard) :) -- t�l�phone : 03.90.24.00.19 courriel : marc.chantreux@ulpmm.u-strasbg.fr ---------------------------------------
le 08/09/2006, Clement Hermann nous �crivait :
Pour info, ça marche aussi avec bash ça (pas les tableaux par contre, l'implémentation des tableaux en bash est différente semble-t-il). Il me semble avoir entendu quelqu'un dire que c'était POSIX, mais je ne saurais l'affirmer :)
Verfie par toi même : http://standards.ieee.org/catalog/olis/posix.html http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html perso, je n'ai rien lu relatif a ${// -- t�l�phone : 03.90.24.00.19 courriel : marc.chantreux@ulpmm.u-strasbg.fr ---------------------------------------
participants (3)
-
Bruno Bonfils
-
Clement Hermann
-
Marc Chantreux