Erro de sintaxe Bash: fim de arquivo inesperado

98

Perdoe-me por este é um script muito simples em Bash. Aqui está o código:

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

depois de executar sh file.sh:

erro de sintaxe: fim de arquivo inesperado

Markcruz
fonte

Respostas:

137

Acho que file.sh está com terminadores de linha CRLF.

corre

dos2unix file.sh

então o problema será corrigido.

Você pode instalar o dos2unix no ubuntu com este:

sudo apt-get install dos2unix
clyfish
fonte
Qual é a razão por trás desse problema? Normalmente trabalho no Windows, mas preciso transferir scripts para sistemas Unix.
CMCDragonkai
A nova linha no Windows é "\ r \ n", enquanto no Linux é "\ n".
clyfish
8
@KeesdeKooter Eu não diria apenas porque algo não funcionou para você que você deveria votar negativamente, claramente funcionou para os 28 votos positivos. Um simples que não funcionou para mim é suficiente. É por isso que o SO permitiu várias respostas para uma pergunta, porque pode haver várias soluções para um problema.
Jeff Wilbert
2
Usando o editor notepad ++ Editar> Conversão EOL> Formato Mac antigo resolvido para mim.
raktale de
Se você pode editar seu arquivo bash com o Notepad ++. Vá para Editar-> Conversão EOL-> Macintosh (CR). Altere para Macintosh (CR) mesmo se estiver usando o sistema operacional Windows.
Juniar de
126

Outra coisa a verificar (apenas me ocorreu):

  • terminar corpos de funções de linha única com ponto e vírgula

Ou seja, este snippet de aparência inocente causará o mesmo erro:

die () { test -n "$@" && echo "$@"; exit 1 }

Para deixar o analisador burro feliz:

die () { test -n "$@" && echo "$@"; exit 1; }
Ulidtko
fonte
3
+1 Também se aplica a trechos de código com colchetes como: [["$ #" == 1]] && [["$ arg" == [1,2,3,4]]] && printf "% s \ n "" blá "|| {printf "% s \ n" "blahblah"; uso; } ............ Observe que o ponto-e-vírgula dentro dos colchetes ondulados, logo após chamar alguma função definida anteriormente 'uso'. Esquecer isso resultará no mesmo erro de sintaxe: eof inesperado.
Cbhihe
você acertou em cheio. Na verdade, o mais simples ;é que se espera que a instrução Every termine com, de ;modo que no final, por exemplo: if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fiirá produzir aquele erro, enquanto if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi;que não ... observe os pequenos pontos-e-vírgulas no final, ou seja: após .bashe fi.
Emmanuel Mahuni
1
Eu tinha isso em um script compartilhado comigo por um zshusuário. O ex funciona em zshmas não no shnem bash. Queria ser 4 pessoas para poder dar 4 votos positivos
Davos
40

Também acabei de receber esta mensagem de erro ao usar a sintaxe errada em uma ifcláusula

  • else if (erro de sintaxe: fim de arquivo inesperado)
  • elif (sintaxe correta)

eu depurei comentando bits até que funcionou

Marengaz
fonte
Muito obrigado .. alguém, por favor, dê uma medalha a esse cara
Happiehappie
16

uma cláusula não fechada if => fi também aumentará isso

dica: use trap para depurar, se seu script for enorme ...

por exemplo

set -x
trap read debug
theRiley
fonte
1
Eu esqueci exatamente o "fi"! Obrigado :) Se você pudesse, para o benefício de todos, fale um pouco sobre sua dica de uso de armadilha.
Carles Alcolea
3
desculpe pela demora, meu amigo. 'o comando' trap 'é uma maneira de depurar seus scripts, quebrando-os essencialmente após cada linha. uma discussão mais completa está aqui: stackoverflow.com/questions/9080431/…
theRiley
1
Isso foi muito útil, obrigado. Observe que o unexpected end of fileerro ocorrerá assim que fifor atingido.
Stephane B.
8

Eu obtive essa resposta com este problema semelhante no StackOverflow

Abra o arquivo no Vim e tente

:set fileformat=unix

Converta as terminações de linha em terminações unix e veja se isso resolve o problema. Se estiver editando no Vim, digite o comando: set fileformat = unix e salve o arquivo. Vários outros editores têm a capacidade de converter finais de linha, como Notepad ++ ou Atom

Obrigado @lemongrassnginger

Jay Killeen
fonte
Essas são apenas formas alternativas de fazer o dos2unixque a resposta aceita aconselha.
ulidtko
7

no cygwin eu precisava: -

 export SHELLOPTS
 set -o igncr

em .bash_profile. Dessa forma eu não precisei rodar o unix2dos

zzapper
fonte
6

Então eu encontrei este post e as respostas não me ajudaram, mas eu consegui descobrir porque ele me deu o erro. eu tive um

cat > temp.txt < EOF
some content
EOF

O problema era que copiei o código acima para estar em uma função e, inadvertidamente, tabulei o código. É necessário certificar-se de que o último EOF não seja tabulado.

Rafael Urena
fonte
1
Este foi exatamente o meu caso. Eu tinha EOFrecuado quatro espaços e o bash não o analisou por causa disso. Remover espaços corrigiu o problema.
aexl
5

Tive o problema quando escrevi a instrução "if - fi" em uma linha:

if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fi

Escrever multilinha resolveu meu problema:

if [ -f ~/.git-completion.bash ]; then 
    . ~/.git-completion.bash
 fi
Sergey
fonte
3

Isso estava acontecendo comigo quando eu estava tentando chamar uma função usando parênteses, por exemplo

run() {
  echo hello
}

run()

deveria estar:

run() {
  echo hello
}

run
Christian Scott
fonte
2

PARA WINDOWS:

No meu caso, estava trabalhando no sistema operacional Windows e recebi o mesmo erro ao executar o autoconf.

  • Simplesmente abro o arquivo configure.ac com meu NOTEPAD ++ IDE.
  • Então eu converti o arquivo com conversão EOL para Windows (CR LF) da seguinte maneira:

    EDITAR -> CONVERSÃO EOL -> WINDOWS (CR LF)

Juniar
fonte
1

Consegui recortar e colar seu código em um arquivo e ele funcionou corretamente. Se você executá-lo assim, ele deve funcionar:

Seu "file.sh":

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

O comando:

$ ./file.sh arg1 arg2 arg3

Observe que "file.sh" deve ser executável:

$ chmod +x file.sh

Você pode estar recebendo esse erro por causa de como está fazendo a entrada (com um cano, cenoura, etc.). Você também pode tentar dividir a condição em duas:

if [ $# -lt 3 ] || [ $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

Ou, já que está usando bash, você pode usar a sintaxe integrada:

if [[ $# -lt 3 || $# -gt 3 ]]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

E, finalmente, você pode, é claro, apenas verificar se 3 argumentos foram fornecidos (limpar, mantém a compatibilidade do shell POSIX):

if [ $# -ne 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi
Aaronstacia
fonte
eu ainda tenho o mesmo erro. Não tenho certeza de onde o código está errado
markcruz
estranho, eu recortei e colei seu código e funcionou conforme o esperado. houve mais saída de erro? muito tempo o bash listará um número de linha. Além disso, qual sistema você está executando? (Linux, MacOS, BSD, distro, etc)
aaronstacy
0

Acabei de recortar e colar seu exemplo em um arquivo; funcionou bem no bash. Eu não vejo nenhum problema com isso.

Para uma boa medida, você pode querer garantir que termine com uma nova linha, embora o bash não deva se importar. (Funciona para mim com e sem a nova linha final.)

Às vezes, você verá erros estranhos se incorporar acidentalmente um caractere de controle ao arquivo. Como é um script curto, tente criar um novo script colando-o de sua pergunta aqui no StackOverflow ou simplesmente digitando-o novamente.

Qual versão do bash você está usando? ( bash --version)

Boa sorte!

Adam Liss
fonte
0

Certifique-se de que o nome do diretório no qual o arquivo .sh está presente não tenha um caractere de espaço. Por exemplo: digamos que se estiver em uma pasta chamada 'Nova pasta', você certamente encontrará o erro que citou. Em vez disso, apenas nomeie como 'New_Folder'. Eu espero que isso ajude.


fonte
0

Aparentemente, algumas versões do shell também podem emitir essa mensagem quando a linha final do seu script não tem uma nova linha.

triplo
fonte
0

No Ubuntu:

$ gedit ~/.profile

Então, File -> Save ase definir end lineparaUnix/Linux

Neb
fonte
0

Eu sei que estou muito atrasado para a festa. Espero que isso possa ajudar alguém.

Verifique seu arquivo .bashrc. Talvez renomeie ou mova.

Discussão aqui: Não é possível obter um script bash simples

viggy28
fonte
0

Para pessoas que usam MacOS:

Se você recebeu um arquivo no formato Windows e queria rodar no MacOS e está vendo este erro, execute estes comandos.

brew install dos2unix
sh <file.sh>
vmorusu
fonte
0

A falta de uma chave de fechamento em uma definição de função causará esse erro, como acabei de descobrir.

function whoIsAnIidiot() {
    echo "you are for forgetting the closing brace just below this line !"

Que claro que deveria ser assim ...

function whoIsAnIidiot() {
    echo "not you for sure"
}
Mike
fonte
0

No meu caso, há redundância \no seguinte:

function foo() {
    python tools/run_net.py \
                           --cfg configs/Kinetics/X3D_8x8_R50.yaml \
                           NUM_GPUS 1 \
                           TRAIN.BATCH_SIZE 8 \
                           SOLVER.BASE_LR 0.0125 \
                           DATA.PATH_TO_DATA_DIR ./afs/kinetics400 \
                           DATA.PATH_PREFIX  ./afs/kinetics400  \  # Error
}

não um \, no final deDATA.PATH_PREFIX ./afs/kinetics400

1
fonte