Parar funções do bash sobre variáveis globais

0

Aqui está uma extração de um script bash para reconfigurar o grub

    OLD="/etc/default/grub"
    NEW="/tmp/default.grub"
    SEC="1"

    cp "$OLD" "$NEW" || { >&2 echo "Couldn't copy $OLD" && exit 1; }

    sed -i "s/GRUB_TIMEOUT=[0-9]\+/GRUB_TIMEOUT=3/$SEC" "$NEW"

    cp_if_change_confirmed "$NEW" "$OLD"

    diff "$OLD" "$NEW" >/dev/null 2>&1 && \
    {
        CFG="$NEW.made"

        grub2-mkconfig --output="$CFG"

        echo "made $CFG from $NEW"

        cp_if_change_confirmed "$CFG" "/boot/grub2/grub.cfg"

        echo rm "$CFG"
        rm "$CFG"
    }

    echo rm "$NEW"
    rm "$NEW"

As saídas finais echo e rm linhas

rm /tmp/default.grub.made
rm /tmp/default.grub.made
rm: cannot remove ‘/tmp/default.grub.made:‘ No such file or directory

De alguma forma, NEW está sendo atribuído ao valor de CFG .

Olhando em cp_if_change_confirmed , que é uma função bash, contém

NEW="$1"

O que eu acho que explica o problema - essas variáveis não têm escopo limitado o suficiente.

Mas isso é um problema de manutenção - preciso incluir funções de terceiros e saber que elas não vão atrapalhar os valores no script pai.

Posso fazer isso no bash, ou é um caso sem esperança e eu só preciso ficar atento a nomes de variáveis ou usar uma linguagem real?

    
por spraff 07.10.2016 / 12:59

1 resposta

1

Use local . Observe que o bash tem o escopo de função somente (como var em JavaScript), não bloqueia o escopo.

myfunc() {
    local foo bar=$1 baz=$2
    foo=/tmp/$bar
    echo "value inside: $foo, $bar"
}
foo=123 bar=234
myfunc quux
echo "value outside: $foo, $bar"

Se você tem um bloco que não precisa de nenhuma persistência, você pode chamar um subshell usando ( ... ) :

foo=123
( foo=345; echo "value inside: $foo" )
echo "value outside: $foo"

Observe que os subshells têm a sobrecarga total de fork () - eles são processos independentes. Além disso, eles não permitem que você escolha quais variáveis localizar - é tudo ou nada.

    
por 07.10.2016 / 13:06