J'ai donc commencé à utiliser zsh
. Je l'aime bien. Cela semble très cool et lisse, et le fait que le répertoire de travail actuel et la ligne de commande réelle soient sur des lignes différentes est sympa, mais en même temps, je remarque que cela zsh
peut être un peu plus lent que bash
, surtout lors de l'impression de texte sur le écran.
Ce que j'ai préféré, c'est le fait qu'il zsh
était «rétrocompatible» avec toutes les fonctions que j'ai définies dans mon .bashrc
.
Un reproche cependant. Toutes les fonctions fonctionnent parfaitement, mais je ne peux pas comprendre comment fonctionne le système d'exportation.
J'ai .bashrc
exporté certaines de ces fonctions afin de pouvoir les utiliser ailleurs, comme dans des scripts et des programmes externes, avec export -f
.
Dans zsh, l'exportation ne semble même pas être discutée. S'agit-il d'un chargement automatique? Ces deux choses sont-elles les mêmes? J'ai beaucoup de mal à comprendre cela.
la source
Réponses:
Les variables d'environnement contenant des fonctions sont un hack bash. Zsh n'a rien de similaire. Vous pouvez faire quelque chose de similaire avec quelques lignes de code. Les variables d'environnement contiennent des chaînes; les anciennes versions de bash, avant la découverte de Shellshock , stockaient le code de la fonction dans une variable dont le nom est celui de la fonction et dont la valeur est
() {
suivie du code de la fonction suivi de}
. Vous pouvez utiliser le code suivant pour importer des variables avec cet encodage et tenter de les exécuter avec des paramètres de type bash. Notez que zsh ne peut pas émuler toutes les fonctionnalités de bash, tout ce que vous pouvez faire est de vous rapprocher un peu (par exemple, pour$foo
diviser la valeur et étendre les caractères génériques, et créer des tableaux basés sur 0).(Comme l'a noté Stéphane Chazelas , le découvreur d'origine de Shellshock, une version antérieure de cette réponse pourrait exécuter du code arbitraire à ce stade si la définition de la fonction était incorrecte. Cette version ne fonctionne pas, mais bien sûr dès que vous exécutez une commande, il peut s'agir d'une fonction importée de l'environnement.)
Les versions post-Shellshock des fonctions d'encodage bash dans l'environnement utilisent des noms de variables invalides (par exemple
BASH_FUNC_myfunc%%
). Cela les rend plus difficiles à analyser de manière fiable car zsh ne fournit pas d'interface pour extraire ces noms de variables de l'environnement.Je ne recommande pas de faire ça. Se fier aux fonctions exportées dans les scripts est une mauvaise idée: cela crée une dépendance invisible dans votre script. Si jamais vous exécutez votre script dans un environnement qui n'a pas votre fonction (sur une autre machine, dans une tâche cron, après avoir changé vos fichiers d'initialisation du shell,…), votre script ne fonctionnera plus. Au lieu de cela, stockez toutes vos fonctions dans un ou plusieurs fichiers séparés (quelque chose comme
~/lib/shell/foo.sh
) et démarrez vos scripts en important les fonctions qu'il utilise (. ~/lib/shell/foo.sh
). De cette façon, si vous modifiezfoo.sh
, vous pouvez facilement rechercher les scripts qui en dépendent. Si vous copiez un script, vous pouvez facilement trouver les fichiers auxiliaires dont il a besoin.Zsh (et ksh avant) rend cela plus pratique en fournissant un moyen de charger automatiquement les fonctions dans les scripts où elles sont utilisées. La contrainte est que vous ne pouvez mettre qu'une seule fonction par fichier. Déclarez la fonction comme chargée automatiquement et placez la définition de la fonction dans un fichier dont le nom est le nom de la fonction. Placez ce fichier dans un répertoire répertorié dans
$fpath
(que vous pouvez configurer via laFPATH
variable d'environnement). Dans votre script, déclarez les fonctions chargées automatiquement avecautoload -U foo
.De plus, zsh peut compiler des scripts, pour gagner du temps d'analyse. Appelez
zcompile
pour compiler un script. Cela crée un fichier avec l'.zwc
extension. Si ce fichier est présentautoload
, le fichier compilé sera chargé à la place du code source. Vous pouvez utiliser lazrecompile
fonction pour (re) compiler toutes les définitions de fonction dans un répertoire.la source
bash
(ne vérifie pas que le contenu de la variable n'est qu'une définition de fonction et traite n'importe quel nom de variable commeHTTP_HOST
ouLC_X
). Bonne réponse sinon.zsh -c 'functions[f]=$VAR'
est analysé même si laf
fonction n'est jamais appelée). La solution consiste à ne considérer que les variables dont le nom suit un modèle réservé comme ceux-ci$BASH_FUNC_x%%
, mais comme vous le dites,zsh
n'a pas d'API pour les répertorier ou les récupérer. Vous auriez besoin d'appelerperl
par exemple.Si vous mettez votre déclaration de fonction dans .zshenv , votre fonction sera utilisable à partir d'un script sans aucun effort.
la source
.zshenv
dedans et cela ralentit chaque invocation de zsh en analysant beaucoup de code qui n'est jamais utilisé. De plus, ce n'est pas la même chose que l'exportation d'une fonction, tout comme une variable exportée, une fonction exportée n'est disponible que pour les processus enfants. Alors que le contenu que vous mettez.zshenv
est disponible pour tous les zsh..zshenv
, tous vos scripts seront totalement non portables. Normalement, les scripts peuvent dépendre les uns des autres, ce qui est bien, vous les distribuez ensemble. Mais s'ils dépendent de la présence de fonctions spéciales dans.zshenv
, personne ne voudra les utiliser, ou ils devraient être invoqués avec un spécialZDOTDIR
, empêchant la vôtre.zshenv
d'être exécutée. Ce serait pénible.