Essas citações com escape em \"test\"
me fazem pensar que há alguma confusão sobre as regras de citação do shell, porque o primeiro código funciona como pretendido e $STATUS == \"test\"
não deveria (a menos que você tenha escrito STATUS='echo '"test"''
ou algo semelhante ).
Para esclarecer adequadamente essa confusão, é necessário explicar alguns conceitos de shell.
Citação
Em shells POSIX, a cotação é um dos mecanismos mais importantes. Infelizmente, também é um tópico muito confuso e, quando usado incorretamente, uma grande fonte de bugs e comportamentos estranhos em scripts.
As regras básicas são as seguintes:
-
Caractere de escape
\
: Preserva o valor literal do próximo caractere seguinte, com exceção de <newline>
.
-
Aspas duplas
"
: Preserva o valor literal de todos os caracteres entre aspas, com exceção de $
, '
, \
e, quando a expansão de histórico está ativada, !
.
-
Aspas simples
'
: Preserva o valor literal de todos os caracteres dentro das aspas, sem exceções.
Substituição de comandos
A substituição de comandos permite que a saída de um comando substitua o comando em si. Sua sintaxe é $(command)
ou 'command'
, embora a primeira seja preferida.
Comando de teste
O comando test
(também conhecido como [
em POSIX e [[
em shells como bash, ksh e zsh) permite usar várias expressões aritméticas e condicionais úteis. Por exemplo, ele pode verificar se um determinado arquivo regular existe e é legível, se duas sequências são iguais ou se um número é maior que outro.
Agora, analisando o código:
STATUS='echo "test"'
A substituição de comando aqui é inútil, já que poderia ter sido escrita como STATUS="test"
. Observe que as aspas duplas não são impressas por echo
, portanto STATUS
contém test
como seu valor.
if [ $STATUS == "test" ]; then
exit 0
fi
Aqui estão, pelo menos, 3 possíveis falhas:
- O
$STATUS
sem aspas pode ser afetado pela divisão de palavras.
-
==
é sintaxe não POSIX. Use =
se você se importa com a portabilidade.
-
if
e exit 0
são inúteis neste cenário, pois [
já faz o trabalho pretendido.
Além disso, observe que, como a linha de código anterior, as aspas duplas não são consideradas literalmente, portanto, o comando resultante (após a remoção da expansão e da cotação) é [ test = test ]
, o que é verdadeiro.
Mas se sua meta fosse ter "test"
como o valor de STATUS
,
STATUS=\"test\"
STATUS="\"test\""
STATUS='"test"'
são todas as atribuições válidas e
[ "$STATUS" = \"test\" ]
[ "$STATUS" = "\"test\"" ]
[ "$STATUS" = '"test"' ]
são todas expressões condicionais válidas.