Errore di syntax BASH vicino al token imprevisto “done”

Qualche idea su quale potrebbe essere il problema?

Il mio codice è:

#!/bin/bash while : do echo "Press [CTRL+C] to stop.." sleep 1 done 

Lo ha salvato come .sh e ha eseguito bash file.sh

CentOS 6 a 32 bit

Qual’è il problema? La prima volta che uso MAI, ne ho bisogno per un semplice ciclo infinito su qualcosa.

Esegui cat -v file.sh

Molto probabilmente hai un ritorno a capo o uno spazio senza interruzioni nel tuo file. cat -v le mostrerà come ^M e M-BM- o M- rispettivamente. Mostrerà allo stesso modo qualsiasi altro strano personaggio che potresti avere nel tuo file.

Rimuovere le interruzioni di riga di Windows con

 tr -d '\r' file.sh > fixedfile.sh 

Stavo ottenendo lo stesso errore su Cygwin; Ho fatto quanto segue (uno di essi lo ha risolto):

  1. TABS convertiti in SPACES
  2. ha eseguito dos2unix sul file .(ba)sh

Qual è l’errore che stai ottenendo?

 $ bash file.sh test.sh: line 8: syntax error: unexpected end of file 

Se ottieni questo errore, potresti avere terminazioni di riga sbagliate. Unix usa alla fine del file mentre Windows usa . Quel personaggio viene interpretato come un personaggio.

Puoi usare od -a test.sh per vedere i caratteri invisibili nel file.

 $ od -a test.sh 0000000 # ! / bin / bash cr nl # sp cr 0000020 nl while sp : cr nl do cr nl sp sp 0000040 sp sp echo sp " P ress sp [ C 0000060 TRL + C ] sp to sp stop " cr 0000100 nl sp sp sp sp sleep sp 1 cr nl do 0000120 ne cr nl 0000124 

La sp sta per space, ht sta per tab, cr sta per e nl sta per . Nota che tutte le linee terminano con cr seguito da un carattere nl .

Puoi anche usare cat -v test.sh se il tuo comando cat prende il parametro -v .

Se hai dos2unix sulla tua scatola, puoi usare quel comando per correggere il tuo file:

 $ dos2unix test.sh 

A volte questo errore si verifica a causa di caratteri CR inattesi nel file, in genere perché il file è stato generato su un sistema Windows che utilizza terminazioni di linea CR. Puoi risolvere questo problema eseguendo os2unix o tr , ad esempio:

tr -d ‘\ 015’ newscript.sh

Ciò rimuove qualsiasi carattere CR dal file.

Apri un nuovo file chiamato foobar

 nano -w foobar 

Script di input

  #!/bin/bash while [ 0 = 0 ]; do echo "Press [CTRL+C] to stop.." sleep 1 done; 

Esci e salva

CTRL + X poi Y e Invio

Imposta script eseguibile ed esegui

 chmod +x foobar ./foobar 

Potrebbe aiutare qualcun altro: ho riscontrato lo stesso tipo di problemi mentre avevo fatto alcuni “copia-incolla” da un documento di Microsoft Word, dove ho preso appunti, ai miei script di shell.

Riscrivendo, manualmente, lo stesso identico codice nello script ha appena risolto questo problema.

All’inizio era abbastanza incomprensibile, penso che i caratteri nascosti e / o la formattazione di Word fossero il problema. Ovvio ma non visibile … Ho perso circa un’ora su questo (non sono un esperto di shell, come puoi immaginare …)

Modifica il tuo codice in qualsiasi ambiente Linux, quindi non dovrai affrontare questo problema. Se modifichi in un blocco note di Windows qualsiasi spazio, prendilo come ^ M.

Ho esattamente lo stesso problema di cui sopra e mi ha portato tutto il giorno a scoprire che non mi piace il mio approccio newline. Invece ho riutilizzato lo stesso codice con approccio semi-colon. Ad esempio il mio codice iniziale che utilizza la nuova riga (che ha generato lo stesso errore del tuo):

 Y=1 while test "$Y" -le "20" do echo "Number $Y" Y=$[Y+1] done 

E usando il codice con approccio a punto e virgola con meraviglia lavorata:

 Y=1 ; while test "$Y" -le "20"; do echo "Number $Y"; Y=$[Y+1] ; done 

Ho notato che lo stesso problema si verifica anche per altri comandi che utilizzano l’approccio newline, quindi penso che mi limiterò a usare il punto e virgola per il mio codice futuro.

C’è un modo per ottenere questo problema senza aver mescolato i problemi di nuova linea (almeno nella mia shell, che è GNU bash v4.3.30):

 #!/bin/bash # foo.sh function foo() { echo "I am quoting a thing `$1' inside a function." } while [ "$input" != "y" ]; do read -p "Hit `y' to continue: " -n 1 input echo done foo "What could possibly go wrong?" 
 $ ./foo.sh ./foo.sh: line 11: syntax error near unexpected token `done' ./foo.sh: line 11: `done' 

Questo perché bash espande i backtick all’interno di stringhe tra virgolette doppie (vedere il manuale di bash sulla quotatura e la sostituzione dei comandi ) e, prima di trovare un apice di corrispondenza, interpreterà le virgolette doppie aggiuntive come parte della sostituzione di comando:

 $ echo "Command substitution happens inside double-quoted strings: `ls`" Command substitution happens inside double-quoted strings: foo.sh $ echo "..even with double quotes: `grep -E "^foo|wrong" foo.sh`" ..even with double quotes: foo "What could possibly go wrong?" 

È ansible aggirare questo evitando i backtick nella stringa con una barra rovesciata o utilizzando una stringa con quotatura singola.

Non sono proprio sicuro del motivo per cui questo fornisce l’unico messaggio di errore, ma penso che abbia a che fare con la definizione della funzione:

 #!/bin/bash # a.sh function a() { echo "Thing's `quoted'" } a while true; do echo "Other `quote'" done 
 #!/bin/bash # b.sh echo "Thing's `quoted'" while true; do echo "Other `quote'" done 
 $ ./a.sh ./a.sh: line 10: syntax error near unexpected token `done' ./a.sh: line 10: `done' $ ./b.sh ./b.sh: command substitution: line 6: unexpected EOF while looking for matching `'' ./b.sh: command substitution: line 9: syntax error: unexpected end of file Thing's quote' ./b.sh: line 7: syntax error near unexpected token `done' ./b.sh: line 7: `done'