Expansão de parâmetros
A resposta óbvia é usar uma das formas especiais de expansão de parâmetros:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
Ou melhor (consulte a seção 'Posição das aspas duplas' abaixo):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
A primeira variante (usando just ?
) requer que STATE seja definido, mas STATE = "" (uma sequência vazia) está OK - não exatamente o que você deseja, mas a notação alternativa e antiga.
A segunda variante (usando :?
) requer que DEST seja definido e não esteja vazio.
Se você não fornecer nenhuma mensagem, o shell fornecerá uma mensagem padrão.
A ${var?}
construção é portátil de volta à Versão 7 UNIX e ao Bourne Shell (1978 ou nos próximos anos). A ${var:?}
construção é um pouco mais recente: acho que estava no System III UNIX por volta de 1981, mas pode ter sido no PWB UNIX antes disso. Está, portanto, no Korn Shell e nos shells POSIX, incluindo especificamente o Bash.
Geralmente é documentado na página de manual do shell em uma seção chamada Expansão de parâmetros . Por exemplo, o bash
manual diz:
${parameter:?word}
Exibir erro se nulo ou não definido. Se o parâmetro for nulo ou não definido, a expansão da palavra (ou uma mensagem nesse sentido se a palavra não estiver presente) será gravada no erro padrão e o shell, se não for interativo, será encerrado. Caso contrário, o valor do parâmetro é substituído.
O comando do cólon
Provavelmente devo acrescentar que o comando dois pontos simplesmente tem seus argumentos avaliados e depois é bem-sucedido. É a notação de comentário do shell original (antes de ' #
' até o final da linha). Por um longo tempo, os scripts de shell Bourne tiveram dois pontos como o primeiro caractere. O Shell C leria um script e usaria o primeiro caractere para determinar se era para o Shell C (um #
hash ' ') ou o shell Bourne ( :
dois pontos ' '). Então o kernel entrou em ação e adicionou suporte aos comentários ' #!/path/to/program
' e o shell Bourne recebeu ' #
', e a convenção do cólon foi esquecida. Mas se você encontrar um script que comece com dois pontos, agora saberá o porquê.
Posição de aspas duplas
blong perguntou em um comentário :
Alguma opinião sobre essa discussão? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
A essência da discussão é:
… No entanto, quando eu shellcheck
(com a versão 0.4.1), recebo esta mensagem:
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
Algum conselho sobre o que devo fazer neste caso?
A resposta curta é "faça o que shellcheck
sugere":
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Para ilustrar o motivo, estude o seguinte. Observe que o :
comando não ecoa seus argumentos (mas o shell avalia os argumentos). Queremos ver os argumentos, portanto, o código abaixo usa printf "%s\n"
no lugar de :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
Observe como o valor em $x
é expandido para primeiro *
e depois para uma lista de nomes de arquivos quando a expressão geral não está entre aspas duplas. Isto é o que shellcheck
está recomendando que deve ser corrigido. Não verifiquei que ela não se opõe ao formulário em que a expressão está entre aspas duplas, mas é uma suposição razoável de que estaria tudo bem.