7
votes

bash: fonction + source + déclarer = boom

Voici un problème: strong>

dans mes scripts Bash, je veux créer plusieurs fichiers avec quelques chèques, donc j'ai: p> xxx pré>

Naïvement j'ai essayé de créer une fonction qui fait: p> xxx pré>

mais il y a un accrochage là-bas. P>

Si l'un des fichiers foo , bar code>, etc. Avoir un global tel que - p> xxx pré>

- il deviendra efficacement: P>

function safe_source() {
  # ...
  declare GLOBAL_VAR=42
  # ...
}


4 commentaires

Peut-être que cela fonctionne si vous utilisez exporter au lieu de déclarer ?


Je simplifiais. En fait, j'ai utilisé declare -r (lecture en lecture seule), et parfois déclarer -ri (lecture seule, entier). Lorsque je dépose le déclarer Les choses fonctionnent bien, je peux également utiliser lisonly en cas de besoin, mais je ne trouve pas d'alternative à déclarer - -Je . BTW, déclarer -x à l'intérieur d'une fonction est toujours un local.


Avez-vous vraiment besoin d'utiliser déclarer -i est son utilisation immuable? Je pourrais envisager de simplement l'ignorer, car je suis tout à fait sûr qu'il n'y a pas de solution pour ce que vous essayez de réaliser avec déclarer :)


Je pense que vous voulez dire que (Python, Perl, Ruby) rendrait votre Life pas fichier plus facile, et je pense que vous vouliez nommer votre fonction coffre-fort Pas Enregistrer Source () :) Un effet secondaire de Red Bull, peut-être?


3 Réponses :


1
votes

déclarer à l'intérieur d'une fonction rend la variable locale à cette fonction. Exporter affecte l'environnement des processus enfants non pas des environnements actuels ou parents.

Vous pouvez définir les valeurs de vos variables dans les fonctions et faire le declare -r , déclarer -i ou déclarer -ri après le fait.


0 commentaires

8
votes

Oui, la commande «eval» de Bash peut faire ce travail. «Eval» n'est pas très élégant et peut parfois être difficile à comprendre et à déboguer le code qui l'utilise. J'essaie habituellement de l'éviter, mais Bash vous laisse souvent sans autre choix (comme la situation qui a motivé votre question). Vous devrez peser les avantages et les inconvénients d'utiliser «Eval» pour vous-même.

Quelques fond sur 'Eval'

Si vous n'êtes pas familier avec "eval", c'est une bash construite en commande qui vous attend de que vous transmettez une chaîne comme paramètre. «Eval» interprète de manière dynamique et exécute votre chaîne comme une commande à part entière, dans le contexte et la portée du shell actuel. Voici un exemple de base d'une utilisation commune (affectation de variable dynamique): xxx

Voir le Guide de script Bash avancé pour plus d'informations et des exemples: http://tldp.org/ldp/abs/html/internal.html#evalref < H3> Résoudre votre problème "Source"

pour faire "EVAL" gérer votre problème d'approvisionnement, vous commenceriez en réécrivant votre fonction, "Safe_Source ()". Au lieu d'exécuter la commande, 'Safe_source ()' doit simplement imprimer la commande comme une chaîne sur stdout: xxx

aussi, vous devez modifier vos invocations de fonction, Légèrement, pour exécuter réellement la commande "eval": xxx

(ce sont des backticks / backticotes, BTW.)

Comment ça marche

en bref:

  • Nous avons converti la fonction dans un émetteur de chaîne de commande.
  • Notre nouvelle fonction émet une chaîne d'invocation de commande 'eval'.
  • Nos nouveaux backticks appellent la nouvelle fonction dans un contexte sous-vase, renvoyant la sortie de chaîne de commande 'eval' par la fonction de sauvegarde sur le script principal.
  • Le script principal exécute la chaîne de commande 'eval', capturée par les backtsticks, dans le contexte du script principal.
  • La chaîne de commande 'eval' de la commande 'Eval' est répartie et exécute la chaîne de commande 'eval' dans le contexte du script principal, exécutant l'intégralité du bloc IF-else, y compris (si le fichier existe) exécutant la commande "Source".

    C'est une sorte de complexe. Comme je l'ai dit, 'eval' n'est pas exactement élégant. En particulier, il y a quelques éléments spéciaux que vous devriez remarquer sur les modifications que nous avons apportées:

    • La totalité du bloc IF-Alors-sinon est devenue une chaîne entière double-citée, avec les backslashes à la fin de chaque ligne "cachée" les nouvelles lignes.
    • Certains des caractères spéciaux de coquille tels que "" ") ont été échappés au revers, tandis que d'autres (" $ ") ont été laissés non-échappés.
    • 'ECHO EVAL' a été achuée à l'ensemble de la chaîne de commande.
    • Les points-virgules supplémentaires ont été ajoutés à toutes les lignes où une commande est exécutée pour les terminer, un rôle que les nouvelles lignes (maintenant cachées) effectuées à l'origine.
    • L'invocation de la fonction a été enveloppée dans des backtsks.

      La plupart de ces changements sont motivés par le fait que «eval» ne gérera pas de nouvelles lignes. Il ne peut traiter que de multiples commandes si nous les combinons dans une seule ligne délimitée par des points-virgules, à la place. Les pauses de la nouvelle fonction sont purement une commodité de formatage pour l'œil humain.

      Si l'une de celles-ci n'est pas claire, exécutez votre script avec le drapeau de Bash '-X' (exécution de débogage) allumé, et cela devrait donner vous une meilleure image de exactement ce qui se passe. Par exemple, dans le contexte de la fonction, la fonction produit la chaîne de commande 'eval' en exécutant cette commande: xxx

      puis, dans le contexte principal, le script principal exécute ceci. : xxx

      Enfin, à nouveau dans le contexte principal, la commande EVAL exécute ces deux commandes s'il existe: xxx

      bien chance.


0 commentaires

9
votes

C'est une réponse en retard, mais maintenant déclarer prend en charge le paramètre -g , qui fait une variable globale (lorsqu'elle est utilisée à l'intérieur de la fonction). Mêmes travaux dans le fichier source.

Si vous avez besoin d'une variable globale (lecture exportée), utilisez: xxx


0 commentaires