Shell Script - errore di sintassi vicino al token imprevisto `else '


15

Con il seguente script di shell, perché ricevo errori

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


potresti voler modificare la riga "copia da ...." poiché potrebbe mostrare attualmente qualcosa che non vuoi mostrare. (Tuttavia, spero che queste siano già informazioni modificate, dato che sarebbero davvero pessime per la sicurezza)
Olivier Dulac il

1
@OlivierDulac Se si fa riferimento a nome utente e password in quella riga, questi sono noti a tutti gli utenti del database Oracle. È comune e ben noto fin dall'inizio del database Oracle.
Jåcob,

@OlivierDulac Prego, alcune informazioni su questo dba-oracle.com/t_scott_tiger.htm
Jåcob,

Risposte:


25

Devi interrompere la condizione in ifquesto modo:

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

o in questo modo:

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

Nota: devi anche mettere gli spazi dopo [e prima ].

Il motivo per l' ;interruzione di ifriga o è che la parte condizione dell'istruzione è solo un comando. Qualsiasi comando di qualsiasi lunghezza per essere precisi. La shell esegue quel comando, esamina lo stato di uscita del comando e quindi decide se eseguire la thenparte o la elseparte.

Poiché il comando può essere di qualsiasi lunghezza, è necessario un marcatore per contrassegnare la fine della parte della condizione. Questa è la ;o la nuova riga, seguita da then.

Il motivo degli spazi successivi [è perché [è un comando. Di solito è incorporato nella shell. La shell esegue il comando [con il resto come parametri, incluso l' ]ultimo parametro obbligatorio. Se non si inserisce uno spazio dopo che [la shell proverà ad eseguire [whatevercome comando e fallirà.

Il motivo dello spazio prima del ]è simile. Perché altrimenti non verrà riconosciuto come un parametro a sé stante.


Era test.sh: line 6: [: missing
perfetto

@lesmana. Un buon modo per fornire prima una risposta errata, quindi continuare a modificare prima che qualcun altro fornisca la risposta corretta. Prova a fornire la risposta corretta la prima volta.
Valentin Bajrami,

1
Non considero la mia prima risposta come sbagliata. In effetti, era "perfetto". Semplicemente non ha risolto tutti i problemi della domanda.
lesmana,

if è sintassi, non è un normale comando. È una parola riservata. A differenza di molti altri linguaggi di programmazione, la shell non riconosce le parole riservate ovunque, solo quando sono la prima parola di un comando (con alcune sottigliezze).
Gilles 'SO- smetti di essere malvagio' il

Grazie per il chiarimento. Sono consapevole che si iftratta di sintassi. Stavo cercando di comunicare che la parte relativa alla ifcondizione non è vincolata a una determinata forma dalla sintassi. Ho modificato il testo. Spero sia più chiaro ora.
lesmana,

5

È possibile controllare facilmente gli script della shell utilizzando ShellCheck online (disponibile anche come strumento autonomo).

In questo caso, indicherà che l'istruzione if ha bisogno di spazi, dopo [e prima ], e che è necessario un ;(o una nuova riga) prima di thensulla stessa riga.

Una volta risolto ciò, continuerà a dirti che USER_NAMEviene utilizzato senza essere inizializzato su nulla. Questo perché hai anche una user_namevariabile (caso importante). Lo stesso vale per PASSe pass.

Ti dice anche di usare read -rper smettere readdi manipolare \(potrebbe essere importante per le password, per esempio), e che dovresti citare due volte le variabili quando chiami sqlplusper impedire alla shell di fare accidentalmente il nome del file e la suddivisione delle parole (anche questo è importante se la password, ad esempio, contiene file come globbing di caratteri *o spazi).

Il rientro del codice lo renderà anche più leggibile:

#!/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

Qui ho anche reso possibile l'uso di password con caratteri di spazio iniziali o finali impostando temporaneamente IFSuna stringa vuota per la lettura della password read.

Anche la logica è stata cambiata per salvare se $ORACLE_SID/ $sidè Test. Questo evita di avere la parte operativa principale dello script in un iframo.


Nota che if ([ x = x ]) then (echo yes) fifunziona anche.
Stéphane Chazelas,

@ StéphaneChazelas Ah, sì. E questo può essere interessante dal punto di vista di un programma che genera codice shell, ma non è come si scrivono normalmente le ifdichiarazioni con [ ... ]... :-)
Kusalananda

2

Quando scrivi shvorresti

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

Quando si scrive bash

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

Badate agli spazi, per favore. Deve esserci uno spazio tra [[e il primo operatore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.