Comentários condicionais para shell perigoso

Comentários condicionais para shell perigoso

Aqui está o que estou tentando alcançar.

#!/bin/bash
safemode=on

if [ $safemode == 'off' ];then
  run dangerous code
fi

Tenho 129 linhas perigosas, todas separadas. Qual é a melhor forma de fazer isso?

Responder1

A "melhor maneira" depende fortemente de quanto esforço você considera máximo. Uma maneira bastante fácil é usar &&listas de comandos -connected para uma ligeira modificação no seu exemplo. Você pode usar a construção de teste aritmético do Bash:

#!/bin/bash
safemode=1

(( ! safemode )) && run dangerous code 1
uncritical code
(( ! safemode )) && run dangerous code 2

ou o operador normal baseado em string

#!/bin/bash
safemode=on

[[ $safemode = "off" ]] && run dangerous code 1
uncritical code
[[ $safemode = "off" ]] && run dangerous code 2

Esta é apenas uma notação resumida para o que você já fez: O [[ ... ]]teste produzirá falseif safemodeis not off, portanto, a execução da lista de comandos irá parar no &&.

Pode ser interessante notar que no caso de uma &&lista de comandos encadeada, o código de saída será o do último comando executado, portanto, se safemodeestiver definido, $?estará 1após essas linhas "protegidas" (apenas no caso de você usar o código de saída dessa forma).

Responder2

Se definirmos uma variável safemodecomo um dos dois comandos trueou false, podemos usá-la como prefixo:

#!/bin/sh
safemode=true

safe_mode_off() { safemode=false }

"$safemode" || run dangerous code 1
uncritical code
"$safemode" || run dangerous code 2

Acho que normalmente definiríamos a variável em nosso processamento de opções, então true/ falseé tão fácil quanto on/ off.


Nóspoderiatalvez estenda isso (embora eu não ache necessariamente que devamos) para apenas fazer com que os comandos perigosos se tornem os argumentos para false, assim:

#!/bin/sh
risky=false

safe_mode_off() { risky= }

$risky run dangerous code 1
uncritical code
$risky run dangerous code 2

No entanto, neste caso, a expansão ainda ocorrerá dentro dos argumentos - por exemplo, $(dangerous subcommand)ainda seria executada, então precisaríamos mudar isso para $($risky dangerous subcommand). Acho que isso é muito sujeito a erros para uso sério.

Responder3

Se você quiser uma abreviação, poderá usar um alias. Eles são mais como uma substituição de texto do que qualquer expansão regular, então as construções de sintaxepodeser inserido através deles. Só é necessário ativar explicitamente os scripts Bash e você deseja ter certeza de não ativar acidentalmente aliases indesejados.

#!/bin/bash
unalias -a
shopt -s expand_aliases

# default safe
alias risky='[ "$riskymode" = enabled ] &&'
riskymode=
if [ "$1" = risky ]; then
        riskymode=enabled
fi

echo this is normal
risky echo this is risky

Mas observe que ainda há a ressalva de que a condição ainda é apenas parte de uma &&-list, então isto:

risky echo try something risky || echo oopsie it failed

executaria o echo oopsiemesmo se o modo de risco estivesse desativado.

Mas você poderia fazer:

risky ( echo try something risky || echo oopsie it failed )

ou mesmo

risky if ! echo another risky attempt; then echo another failure; fi

(você pode colocar um comando composto dentro de uma &&lista)


Poderíamos até fazer com que o alias transformasse a linha em um comentário:

#!/bin/bash
unalias -a
shopt -s expand_aliases
alias risky='#'
if [ "$1" = risky ]; then
        alias risky=''
fi
risky echo something risky, again || echo "does it fail now?"

mas é claro que simplesmente ignorará o primeirolinha, então isso executaria novamente a segunda linha no modo "seguro":

risky echo something even more risky ||
    echo "_now_ does it fail?"

informação relacionada