Inicializando variáveis ​​do Bash - é obrigatório, recomendado ou define como você vai

9

Existe alguma vantagem / desvantagem em inicializar o valor de uma variável bash no script, antes do código principal ou de variáveis ​​locais em uma função antes de atribuir o valor real a ele?

Preciso fazer algo assim:

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

init "Mark"

Existe algum risco de as variáveis ​​serem inicializadas com valores de lixo (se não inicializadas) e de terem um efeito negativo nos valores das variáveis?

Cyrus
fonte
2
Onde você conseguiu essa idéia?
6
@DoritoStyle Bem, se alguém é usado para linguagens de nível inferior, como C, isso é perfeitamente válido para se preocupar.
Kusalananda
@ Kusalananda O código C não é equivalente name = ""; name = argv[1];? E isso não é tão inútil?
Joseph Sible-Restabelecer Monica
1
@ JosephSible-ReinstateMonica Sim. O código C que você postou é inútil. Em C, porém, ao contrário do shell, variáveis ​​não inicializadas não têm um valor bem definido específico. Isso significa que a inicialização de variáveis ​​em idiomas como C faz sentido em muitas circunstâncias. Fazer isso no shell não é necessário. Inicializar uma variável em C apenas para defini-la imediatamente com outro valor não faz sentido, como você indica.
Kusalananda

Respostas:

22

Não há benefício em atribuir uma sequência vazia a uma variável e, em seguida, atribuir imediatamente outra sequência variável a ela. Uma atribuição de um valor a uma variável do shell substituirá completamente seu valor anterior.

No meu conhecimento, nenhuma recomendação diz que você deve inicializar explicitamente variáveis ​​para cadeias vazias. De fato, fazer isso pode mascarar erros em algumas circunstâncias (erros que de outra forma seriam aparentes se executados em baixo set -u, veja abaixo).

Uma variável não configurada, que não está sendo usada desde o início de um script ou que não foi definida explicitamente executando o unsetcomando nele, não terá valor. O valor dessa variável não será nada. Se usado como "$myvariable", você obterá o equivalente a ""e nunca obterá "dados de lixo".

Se a opção shell nounsetestiver configurada com um set -o nounsetou set -u, a referência a uma variável não configurada fará com que o shell produza um erro (e um shell não interativo seria encerrado):

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

ou, em bash:

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

As variáveis ​​do shell serão inicializadas pelo ambiente se o nome da variável corresponder a uma variável de ambiente existente.

Se você espera que esteja usando uma variável que pode ser inicializada pelo ambiente dessa maneira (e se for indesejada), poderá desabilitá-la explicitamente antes da parte principal do seu script:

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

o que também a removeria como uma variável de ambiente ou, você pode simplesmente ignorar seu valor inicial e substituí-lo por uma atribuição (o que faria com que a variável de ambiente também alterasse o valor).

Você nunca encontraria lixo não inicializado em uma variável de shell (a menos que, como indicado, esse lixo já existisse em uma variável de ambiente com o mesmo nome).

Kusalananda
fonte
3
Embora não haja um valor para definir uma variável para um valor vazio e, em seguida, imediatamente colocando-o quanto a OP literalmente não, não é de valor na determinação de um valor em branco (ou unsetting) antes de executar algum tipo de forou whilelaço para defini-la para um calculado valor se houver alguma chance de que o loop não seja realmente executado devido às condições que não foram atendidas; e a variável pode ter sido configurada para algum outro valor no ambiente que o script herdou. Mas é sem dúvida melhor colocar tudo em a main()e definir as variáveis ​​como local.
Monty mais dura
Você também pode detectar variáveis ​​não definidas usando os operadores de expansão de parâmetros, omitindo :, por exemplo,${myvariable-defaultvalue}
Barmar
3

Edit : Opa, aparentemente a declaração é diferente da inicialização. De qualquer forma, deixarei isso aqui para que programadores iniciantes como eu possam aprender com o meu erro.


A vantagem de declarar variáveis ​​locais em uma função é que você pode copiar facilmente o código.

Por exemplo, digamos que eu tenho uma função:

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

Se eu quiser transformá-lo em um script, simplesmente ignoro a localinstrução e copio todo o resto:

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

Se a declaração e a atribuição estivessem na mesma linha, eu teria que editar manualmente a localparte antes de poder transformá-la em um script:

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

Neste exemplo, não é grande coisa, mas se você estiver lidando com funções maiores e mais complexas, pode ser mais doloroso.

wjandrea
fonte
1
A questão não era sobre a combinação da declaração e inicialização. Era sobre se inicializar com um valor vazio antes de atribuir um valor real.
Barmar
@ Barmar Oh, eu apenas procurei "inicialização". Eu pensei que era sinônimo de "declaração" ...
wjandrea