Initialisation des variables Bash - Est-elle requise, recommandée ou définie au fur et à mesure

9

Y a-t-il un avantage / un inconvénient à initialiser la valeur d'une variable bash dans le script, soit avant le code principal, soit les variables locales dans une fonction avant de lui affecter la valeur réelle?

Dois-je faire quelque chose comme ça:

init()
{
    name=""
    name=$1
}

init "Mark"

Y a-t-il un risque que les variables soient initialisées avec des valeurs de poubelle (si elles ne sont pas initialisées) et que cela ait un effet négatif sur les valeurs des variables?

Cyrus
la source
2
D'où vous est venue cette idée?
6
@ DoritoStyle Eh bien, si l'on est habitué à des langages de niveau inférieur, comme le C, alors c'est une chose parfaitement valable.
Kusalananda
@Kusalananda N'est-ce pas l'équivalent C de ce code name = ""; name = argv[1];? Et n'est-ce pas aussi inutile?
Joseph Sible-Reinstate Monica
1
@ JosephSible-ReinstateMonica Oui. Le code C que vous avez publié est inutile. En C, cependant, contrairement au shell, les variables non initialisées n'ont pas de valeur bien définie particulière. Cela signifie que l'initialisation de variables dans des langages comme C est logique dans de nombreuses circonstances. Cela n'est pas nécessaire dans le shell. L'initialisation d'une variable en C uniquement pour la définir immédiatement sur une autre valeur est inutile, comme vous le faites remarquer.
Kusalananda

Réponses:

22

Il n'y a aucun avantage à affecter une chaîne vide à une variable, puis à lui affecter immédiatement une autre chaîne variable. Une affectation d'une valeur à une variable shell remplacera complètement sa valeur précédente.

Il n'y a à ma connaissance aucune recommandation qui dit que vous devez explicitement initialiser des variables pour vider des chaînes. En fait, cela peut masquer des erreurs dans certaines circonstances (erreurs qui seraient autrement apparentes si vous exécutez sous set -u, voir ci-dessous).

Une variable non définie, inutilisée depuis le début d'un script ou explicitement annulée en exécutant la unsetcommande dessus, n'aura aucune valeur. La valeur d'une telle variable ne sera rien. S'il est utilisé en tant que "$myvariable", vous obtiendrez l'équivalent de ""et vous n'obtiendrez jamais de "données d'ordures".

Si l'option shell nounsetest définie avec l'un set -o nounsetou l' autre set -u, alors référencer une variable non définie entraînera une erreur du shell (et un shell non interactif se terminera):

$ set -u
$ echo "$myvariable"
/bin/sh: myvariable: parameter not set

ou, en bash:

$ set -u
$ echo "$myvariable"
bash: myvariable: unbound variable

Les variables shell seront initialisées par l'environnement si le nom de la variable correspond à une variable d'environnement existante.

Si vous vous attendez à ce que vous utilisiez une variable qui peut être initialisée par l'environnement de cette manière (et si elle n'est pas souhaitée), alors vous pouvez explicitement la désactiver avant la partie principale de votre script:

unset myvariable    # unset so that it doesn't inherit a value from the environment

ce qui la supprimerait également en tant que variable d'environnement, ou, vous pouvez simplement ignorer sa valeur initiale et la remplacer par une affectation (ce qui ferait également changer la valeur de la variable d'environnement).

Vous ne rencontreriez jamais de déchets non initialisés dans une variable shell (sauf si, comme indiqué, ces déchets existaient déjà dans une variable d'environnement du même nom).

Kusalananda
la source
3
Bien qu'il n'y ait pas de valeur à la mise en une variable à une valeur vide puis mise immédiatement comme l'OP ne littéralement, il est la valeur dans la mise en valeur vide (ou unsetting) avant d'exécuter une sorte de forou whileboucle pour le mettre à un calcul valeur s'il y a une chance que la boucle ne s'exécute pas en raison de la ou des conditions non remplies; et la variable peut avoir été définie sur une autre valeur dans l'environnement dont le script a hérité. Mais il est sans doute préférable de tout mettre dans un main()et de définir les variables comme local.
Monty Harder
Vous pouvez également détecter des variables non définies à l'aide des opérateurs d'expansion de paramètres, en omettant :, par exemple${myvariable-defaultvalue}
Barmar
3

Edit : Oups, apparemment la déclaration est différente de l'initialisation. Je laisserai cela de toute façon afin que les codeurs débutants comme moi puissent apprendre de mon erreur.


L'avantage de déclarer des variables locales dans une fonction est que vous pouvez facilement copier le code.

Par exemple, disons que j'ai une fonction:

foo(){
    local name
    name="$1"
    echo "$name"
}

Si je veux en faire un script, j'ignore simplement l' localinstruction et copie tout le reste:

#!/bin/bash
name="$1"
echo "$name"

Si la déclaration et l'affectation étaient sur la même ligne, je devrais éditer manuellement la localpartie avant de pouvoir la transformer en script:

foo(){
    local name="$1"
    echo "$name"
}

Dans cet exemple, ce n'est pas un gros problème, mais si vous avez affaire à des fonctions plus grandes et plus complexes, cela peut devenir plus douloureux.

wjandrea
la source
1
La question n'était pas de combiner la déclaration et l'initialisation. Il s'agissait de savoir s'il fallait initialiser avec une valeur vide avant d'attribuer une valeur réelle.
Barmar
@Barmar Oh, je viens de chercher "initialisation". Je pensais que c'était synonyme de "déclaration" ...
wjandrea