Синтаксическая ошибка bash: неожиданный конец файла

99

Простите меня за то, что это очень простой скрипт на Bash. Вот код:

#!/bin/bash
# june 2011

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

после запуска sh file.sh:

синтаксическая ошибка: неожиданный конец файла

Markcruz
источник

Ответы:

137

Я думаю, что file.sh с ограничителями строки CRLF.

бегать

dos2unix file.sh

тогда проблема будет устранена.

Вы можете установить dos2unix в ubuntu следующим образом:

sudo apt-get install dos2unix
Клифар
источник
В чем причина этой проблемы? Обычно я работаю в Windows, но мне нужно перенести скрипты в системы unix.
CMCDragonkai 02
Новая строка в Windows - это «\ r \ n», а в Linux - «\ n».
clyfish
8
@KeesdeKooter Я бы не сказал, что вы должны проголосовать против этого только потому, что что-то не сработало для вас, очевидно, это сработало для 28 положительных голосов. У меня просто не работает. Вот почему SO разрешил несколько ответов на вопрос, потому что у проблемы может быть несколько решений.
Джефф Уилберт
2
Использование редактора notepad ++ Edit> EOL Conversion> Old Mac Format решило эту проблему для меня.
raktale
Если вы можете отредактировать файл bash с помощью Notepad ++. Перейдите в Edit-> EOL Conversion-> Macintosh (CR). Измените его на Macintosh (CR), даже если вы используете ОС Windows.
Juniar
127

Еще одна вещь, которую нужно проверить (только что произошло со мной):

  • завершать тела однострочных функций точкой с запятой

Т.е. этот невинно выглядящий фрагмент вызовет ту же ошибку:

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

Чтобы осчастливить тупой парсер:

die () { test -n "$@" && echo "$@"; exit 1; }
улидько
источник
3
+1 Также применяется к фрагментам кода с такими скобками: [["$ #" == 1]] && [["$ arg" == [1,2,3,4]]] && printf "% s \ n "" бла "|| {printf "% s \ n" "бла-бла"; использование; } ............ Обратите внимание, что точка с запятой внутри волнистых скобок сразу после вызова некоторой ранее определенной функции 'usage'. Если вы забудете об этом, то получите ту же синтаксическую ошибку: неожиданный eof.
Cbhihe
ты сделал это. На самом деле, простая вещь заключается в ;том, что оператор Every должен заканчиваться ;так, что в конце, например: if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fiвызовет эту ошибку, тогда как if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi;не ... заметит маленькие точки с запятой в конце, то есть: после .bashи fi.
Эммануэль Махуни
1
У меня было это в скрипте, которым поделился со мной zshпользователь. Бывший делает работу , zshно не в shни bash. Хотелось бы, чтобы меня было 4 человека, чтобы я мог дать эти 4 голоса за
Давос
42

Я также только что получил это сообщение об ошибке из-за неправильного синтаксиса в ifпредложении

  • else if (синтаксическая ошибка: неожиданный конец файла)
  • elif (правильный синтаксис)

Я отлаживал его, комментируя биты, пока он не работал

Маренгаз
источник
Большое спасибо .. кто-нибудь, пожалуйста, дайте этому парню медаль
Happiehappie
17

Незакрытое предложение if => fi также вызовет это

Совет: используйте ловушку для отладки, если ваш скрипт огромен ...

например

set -x
trap read debug
Райли
источник
1
Я точно забыл "фи"! Спасибо :) Если бы вы могли, для всеобщего блага, уточнить свой совет по использованию ловушек.
Карлес
3
извините за задержку, мой друг. Команда 'trap' - это способ отладки ваших скриптов, по сути, прерывание после каждой строки. более подробное обсуждение здесь: stackoverflow.com/questions/9080431/…
theRiley
1
Это было полезно, спасибо большое. Обратите внимание, что unexpected end of fileошибка возникнет, как только будет нажата fiкнопка.
Стефан Б.
8

Я получил этот ответ от аналогичной проблемы на StackOverflow

Откройте файл в Vim и попробуйте

:set fileformat=unix

Преобразуйте окончания строк в окончания unix и посмотрите, решит ли это проблему. Если редактируете в Vim, введите команду: set fileformat = unix и сохраните файл. Некоторые другие редакторы имеют возможность конвертировать окончания строк, например Notepad ++ или Atom.

Спасибо @lemongrassnginger

Джей Киллин
источник
Это просто альтернативные способы сделать так, dos2unixкак советует принятый ответ.
ulidtko
7

на cygwin мне понадобилось: -

 export SHELLOPTS
 set -o igncr

в .bash_profile. Таким образом, мне не нужно было запускать unix2dos

Zzapper
источник
6

Итак, я нашел этот пост, и ответы мне не помогли, но я смог понять, почему он дал мне ошибку. У меня есть

cat > temp.txt < EOF
some content
EOF

Проблема заключалась в том, что я скопировал приведенный выше код для использования в функции и случайно добавил код с помощью вкладки. Необходимо убедиться, что последний EOF не содержит вкладок.

Рафаэль Урена
источник
1
Это был именно мой случай. Я сделал EOFотступ в четыре пробела, и из-за этого bash его не разбирал. Удаление пробелов устранило проблему.
aexl
5

У меня возникла проблема, когда я написал оператор «if-fi» в одну строку:

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

Напишите многострочное решение моей проблемы:

if [ -f ~/.git-completion.bash ]; then 
    . ~/.git-completion.bash
 fi
Сергей
источник
3

Это происходило со мной, когда я пытался вызвать функцию, используя скобки, например

run() {
  echo hello
}

run()

должно быть:

run() {
  echo hello
}

run
Кристиан Скотт
источник
2

ДЛЯ WINDOWS:

В моем случае я работал в ОС Windows и получил ту же ошибку при запуске autoconf.

  • Я просто открываю файл configure.ac в моей среде NOTEPAD ++ IDE.
  • Затем я преобразовал файл с преобразованием EOL в Windows (CR LF) следующим образом:

    РЕДАКТИРОВАТЬ -> КОНВЕРСИЯ EOL -> WINDOWS (CR LF)

Юниар
источник
1

Мне удалось вырезать и вставить ваш код в файл, и он работал правильно. Если вы выполните это так, он должен работать:

Ваш "file.sh":

#!/bin/bash
# june 2011

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

Команда:

$ ./file.sh arg1 arg2 arg3

Обратите внимание, что "file.sh" должен быть исполняемым:

$ chmod +x file.sh

Вы можете получить эту ошибку b / c того, как вы вводите (с трубкой, морковкой и т. Д.). Вы также можете попробовать разделить условие на два:

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

Или, поскольку вы используете bash, вы можете использовать встроенный синтаксис:

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

И, наконец, вы можете, конечно, просто проверить, были ли указаны 3 аргумента (чистый, поддерживает совместимость с оболочкой POSIX):

if [ $# -ne 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi
aaronstacy
источник
У меня все еще та же ошибка. я не совсем уверен, где код идет не так
markcruz
странно, я вырезал и вставил ваш код, и он работал, как ожидалось. была ли еще ошибка вывода? много времени bash будет указывать номер строки. также, какая система у вас работает? (Linux, MacOS, BSD, дистрибутив и т. Д.)
aaronstacy
1

Как я только что обнаружил, отсутствие закрывающей скобки в определении функции вызовет эту ошибку.

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

Что, конечно, должно быть так ...

function whoIsAnIidiot() {
    echo "not you for sure"
}
Майк
источник
0

Я просто вырезал и вставил ваш пример в файл; он отлично работал под bash. Никаких проблем с этим не вижу.

Для большей надежности вы можете убедиться, что он заканчивается новой строкой, хотя bash это не должно заботить. (Он работает для меня как с последней строкой, так и без нее.)

Иногда вы будете видеть странные ошибки, если случайно встроили в файл управляющий символ. Поскольку это короткий сценарий, попробуйте создать новый сценарий, вставив его из своего вопроса здесь, в StackOverflow, или просто повторно набрав его.

Какую версию bash вы используете? ( bash --version)

Удачи!

Адам Лисс
источник
0

Убедитесь, что в имени каталога, в котором находится файл .sh, нет пробела. например: Скажем, если он находится в папке с именем «Новая папка», вы обязательно столкнетесь с указанной ошибкой. Вместо этого просто назовите его «New_Folder». Надеюсь, это поможет.


источник
0

По-видимому, некоторые версии оболочки также могут выдавать это сообщение, когда в последней строке вашего скрипта отсутствует новая строка.

тройной
источник
0

В Ubuntu:

$ gedit ~/.profile

Тогда, File -> Save asи установить end lineвUnix/Linux

Neb
источник
0

Для людей, использующих MacOS:

Если вы получили файл в формате Windows и хотели запустить MacOS и увидели эту ошибку, запустите эти команды.

brew install dos2unix
sh <file.sh>
вморусу
источник
0

В моем случае есть лишнее, \например следующее:

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
}

Существует НЕ\ в концеDATA.PATH_PREFIX ./afs/kinetics400

один
источник