Shell Script - erro de sintaxe próximo ao token inesperado 'else'

13

Com o seguinte shell script, por que estou recebendo erros

syntax error near unexpected token 'else'

Shell Script

echo "please enter username"
read user_name
echo "please enter password"
read -s pass
echo ${ORACLE_SID}
SID=${ORACLE_SID}
if ["${ORACLE_SID}" != 'Test'] then
sqlplus -s -l $USER_NAME/$PASS@$SID <<EOF
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
EOF
else
echo "Cannot copy"
fi
    
por Jåcob 22.08.2013 / 13:36

3 respostas

22

Você precisa encerrar a condição de if da seguinte forma:

if [ "${ORACLE_SID}" != 'Test' ]; then

ou assim:

if [ "${ORACLE_SID}" != 'Test' ]
then

Observação: você também precisa colocar espaços depois de [ e antes de ] .

O motivo do ; ou linebreak é que a parte da condição da instrução if é apenas um comando. Qualquer comando de qualquer comprimento para ser preciso. O shell executa esse comando, examina o status de saída do comando e decide se deve executar a parte then ou a parte else .

Como o comando pode ser de qualquer tamanho, é necessário que haja um marcador para marcar o final da parte da condição. Essa é a ; ou a nova linha, seguida por then .

O motivo dos espaços após [ é porque [ é um comando. Geralmente um builtin do shell. O shell executa o comando [ com o restante como parâmetros, incluindo o ] como último parâmetro obrigatório. Se você não colocar um espaço após [ , o shell tentará executar o comando [whatever as e falhar.

O motivo do espaço antes do ] é semelhante. Porque senão não será reconhecido como um parâmetro próprio.

    
por 22.08.2013 / 13:56
4

Você pode facilmente verificar seus scripts de shell usando o ShellCheck on-line (também disponível como uma ferramenta autônoma).

Nesse caso, ele indicará que a instrução if precisa de espaços, após [ e antes de ] , e que você precisa de um ; (ou uma nova linha) antes do then no mesmo linha.

Quando você consertar isso, ele informará que USER_NAME é usado sem ser inicializado para nada. Isso porque você também tem uma variável user_name (o caso é importante). O mesmo vale para PASS e pass .

Ele também diz para você usar read -r para parar read do mangling \ (pode ser importante para senhas, por exemplo) e que você deve aspas duplas ao chamar sqlplus para evitar o shell acidentalmente fazendo globbing de nomes de arquivos e divisão de palavras (novamente, isso é importante se a senha, por exemplo, contiver caracteres globbing de arquivo como * ou espaços).

Recuar o código também o tornará mais legível:

#!/bin/bash

read -r -p 'please enter username: ' user_name
IFS= read -rs -p 'please enter password: ' pass

printf 'ORACLE_SID = %s\n' "$ORACLE_SID"
sid=$ORACLE_SID

if [ "$sid" = 'Test' ]; then
    echo 'Cannot copy' >&2
    exit 1
fi

sqlplus -s -l "$user_name/$pass@$sid" <<'SQL_END'
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
SQL_END

Aqui, também tornei possível usar senhas com caracteres iniciais ou finais definindo IFS temporariamente como uma string vazia para a leitura de senha read .

A lógica também foi alterada para resgatar se $ORACLE_SID / $sid for Test . Isso evita ter a parte operacional principal do script em uma ramificação if .

    
por 31.12.2016 / 19:19
2

Ao escrever sh , você deseja

if [ "$ORACLE_SID" != "Test" ]
then
  ...
fi

Ao escrever bash

if [[ "$ORACLE_SID" != "Test" ]]
then
  ...
fi

Cuidado com os espaços, por favor. Deve haver um espaço entre [[ e o primeiro operador.

    
por 22.08.2013 / 14:03