2013-10-30 17 views
6

Sto scrivendo uno script di shell per semplificare il mio flusso di lavoro di sviluppo.Perché viene visualizzato un errore "Unario operatore previsto"?

Ci vuole un argomento su quale cartella dei temi sto per lavorare e inizia grunt watch su quella directory.

Se chiamo lo script senza l'argomento necessario, sto attualmente stampando un avviso che un tema deve essere specificato come argomento della riga di comando.

Vorrei stampare un elenco delle opzioni disponibili, ad es. directory a tema

Questo è quello che ho finora ...

THEME=$1 

if [ $THEME == '' ] 
then 
    echo 'Need to specify theme' 
else 
    cd 'workspace/aws/ghost/'$THEME'/' 
    grunt watch 
fi 

Idealmente mi piacerebbe sostituire l'uscita della linea echo con una ls della directory temi genitore in questo modo

THEME=$1 

if [ $THEME == '' ] 
then 
    echo 'Need to specify theme from the following' 
    ls workspace/aws/ghost 
else 
    cd 'workspace/aws/ghost/'$THEME'/' 
    grunt watch 
fi 

Tuttavia questo mi dà il seguente errore

./ghost_dev.sh: line 3: [: ==: unary operator expected 
+1

Dovresti usare '-z' per cercare una variabile vuota:' if [-z "$ THEME"] '. – Kevin

+0

modificato il titolo, proverò con '-z' – Luke

+0

' se [[-z "$ THEME"]] 'funziona perfettamente - grazie. – Luke

risposta

23

È necessario virgolette $THEME qui:

if [ $THEME == '' ] 

caso contrario, quando non si specifica un tema, $THEME espande a nulla, e la shell vede questo errore di sintassi:

if [ == '' ] 

Con citazioni aggiunto, come così:

if [ "$THEME" == '' ] 

l'espansione di un vuoto $THEME cede questo confronto valido invece:

if [ "" == '' ] 

Questa capacità di errori di sintassi runtime può essere sorprendente per coloro il cui sfondo è in linguaggi di programmazione più tradizionali, ma shell di comandi (almeno quelli nella tradizione Bourne) analizzare il codice di un po 'diverso. In molti contesti, i parametri della shell si comportano più come macro che come variabili; questo comportamento fornisce flessibilità, ma crea anche trappole per gli incauti.

Dal momento che hai contrassegnato questa domanda bash, vale la pena notare che non c'è una parola-splitting eseguita sul risultato di espansione di parametro all'interno della "nuova" Sintassi di test disponibili in bash (e ksh/zsh), vale a dire [[. .. ]]. Così si può anche fare questo:

if [[ $THEME == '' ]] 

I posti si possono ottenere via senza virgolette sono elencati here. Ma è comunque una buona abitudine citare sempre le espansioni dei parametri, tranne quando vuoi esplicitamente la divisione delle parole (e anche in questo caso, guarda se gli array risolveranno il tuo problema).

Sarebbe più idiomatico per utilizzare l'operatore -z prova invece di uguaglianza con la stringa vuota:

if [ -z "$THEME" ] 

È tecnicamente non è necessario le virgolette in questo caso semplice; [ -z ] restituisce true. Ma se hai un'espressione più complicata, il parser si confonderà, quindi è meglio usare sempre le virgolette. Naturalmente, [[ ... ]] non richiede le virgolette qui, o:

if [[ -z $THEME ]] 

Ma [[ ... ]] non è parte dello standard POSIX; del resto, neanche lo è ==. Quindi, se ti interessa la stretta compatibilità con altre shell POSIX, attenersi alla soluzione di quotatura e utilizzare -z o un singolo =.

+0

OK, ho aggiunto le virgolette sull'assegnazione delle variabili, usato la sintassi [[]] e aggiunto le virgolette su "$ TEMA" per le migliori pratiche. Funziona a meraviglia! Grazie. – Luke

+3

Le assegnazioni funzionano in modo leggermente diverso; almeno la divisione delle parole non si verifica sul RHS, quindi penso che 'THEME =" $ 1 "' e 'THEME = $ 1' siano identici, anche se mi piacerebbe essere corretto per il caso d'angolo che sto dimenticando. – chepner

+0

@chepner - hai ragione, non c'è bisogno di virgolette intorno alle espansioni sul lato destro di un compito. Ancora bisogno di citare qualsiasi spazio bianco letterale, ovviamente. –

0

Si prega di correggere la sintassi con le virgolette.

if [ "$THEME" == "" ] then 
    echo 'Need to specify theme from the following' 
    ls workspace/aws/ghost 
2

[ "$THEME" ] considerato falso se $THEME è indefinito o una stringa vuota e vero il contrario. Vedi http://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html#Bash-Conditional-Expressions. È possibile riorganizzare la vostra istruzione if a sfruttare questo comportamento e hanno una condizione ancora più semplice:

 
if [ "$THEME" ]; then 
    cd 'workspace/aws/ghost/'$THEME'/' 
    grunt watch 
else 
    echo 'Need to specify theme from the following' 
    ls workspace/aws/ghost 
fi 

"$THEME" necessità di essere tra virgolette, nel caso in cui il suo valore contiene spazi.

Problemi correlati