Синтаксическая ошибка возле неожиданного токена '- bash

У меня есть образец script на моем Mac

#!/bin/bash
test() {
  echo "Example"
}
test
exit 0

и это отлично работает, отображая пример

Когда я запускаю этот script на компьютере RedHat, он говорит

Синтаксическая ошибка рядом с неожиданным токеном

Я проверил, что bash доступен с помощью

cat /etc/shells

which bash shows /bin/bash 

Кто-нибудь сталкивался с той же проблемой?

Спасибо заранее!

Ответ 1

Это может быть проблема с кодировкой файла.

Я столкнулся с проблемами кодирования типов файлов при работе с файлами между различными операционными системами и редакторами - в моем случае, в частности, между Linux и системами Windows.

Я предлагаю проверить кодировку вашего файла, чтобы убедиться, что он подходит для целевой среды linux. Я предполагаю, что проблема с кодировкой менее вероятна, если вы используете MAC, чем если бы вы использовали текстовый редактор Windows, но я думаю, что кодирование файлов по-прежнему стоит рассмотреть.

--- EDIT (добавьте фактическое решение, рекомендованное @Potatoswatter)

Чтобы продемонстрировать, как может быть проблема с кодировкой типа файла, я копирую/вставляю ваш пример script в Блокнот в Windows (у меня нет доступа к Mac), а затем скопировал его на машину Linux и запустил:

[email protected]:~/windows> sh ./originalfile             
./originalfile: line 2: syntax error near unexpected token `$'{\r''
'/originalfile: line 2: `test() {

В этом случае Блокнот сохранил файл с возвратами каретки и переводами строк, вызывая ошибку, показанную выше. \r указывает на возврат каретки (Linux-системы завершают строки только с помощью linefeeds \n).

На машине linux вы можете протестировать эту теорию, выполнив следующую команду, чтобы удалить каретки из файла, если они присутствуют:

cat originalfile | tr -d "\r" > newfile

Затем попробуйте запустить новый файл sh ./newfile. Если это работает, проблема была возвращена каретой в виде скрытых символов.

Примечание. Это не точная репликация вашей среды (у меня нет доступа к Mac), однако мне кажется, что проблема в том, что редактор где-то был сохранен каретка возвращается в файл.

---/EDIT

Чтобы разработать немного, операционные системы и редакторы могут иметь разные значения по умолчанию для кодировки файлов. Как правило, приложения и редакторы будут влиять на используемую кодировку типа файлов, например, Microsoft Notepad и Notepad ++ по умолчанию для Windows-1252. Могут также возникать различия в новой строке (в средах Windows возврат каретки и перевод строки часто используются для завершения строк в файлах, в то время как в Linux и OSX обычно используется только линейный перевод).

Аналогичный вопрос и ответ, который ссылается на кодировку файлов, представлен здесь: плохой символ, отображающийся в bash script исполнении

Ответ 2

попробуйте что-то вроде

$ sudo apt-get install dos2unix
$ dos2unix offendingfile

Ответ 3

Простой способ конвертировать example.sh файл в UNIX, если вы работаете в Windows, - это использовать NotePad ++ (Edit > EOL Conversion > UNIX/OSX Format)

Вы также можете установить EOL по умолчанию в блокнот ++ (Настройки > Настройки > Новый документ/Каталог по умолчанию > выберите Unix/OSX в поле "Формат" )

Ответ 4

Спасибо @jdt за ваш ответ.

После этого, и поскольку я продолжаю иметь эту проблему с возвратом каретки, я написал это маленькое script. Только запустите carriage_return, и вам будет предложено "очистить" файл.

https://gist.github.com/kartonnade/44e9842ed15cf21a3700

alias carriage_return=remove_carriage_return
remove_carriage_return(){

# cygwin throws error like : 
# syntax error near unexpected token `$'{\r''
# due to carriage return
# this function runs the following
# cat originalfile | tr -d "\r" > newfile

read -p "File to clean ? "
file_to_clean=$REPLY
temp_file_to_clean=$file_to_clean'_'

# file to clean => temporary clean file
remove_carriage_return_one='cat '$file_to_clean' | tr -d "\r" > '
remove_carriage_return_one=$remove_carriage_return_one$temp_file_to_clean

# temporary clean file => new clean file
remove_carriage_return_two='cat '$temp_file_to_clean' | tr -d "\r" > '
remove_carriage_return_two=$remove_carriage_return_two$file_to_clean

eval $remove_carriage_return_one
eval $remove_carriage_return_two
# remove temporary clean file 
eval 'rm '$temp_file_to_clean

}

Ответ 5

Я хочу добавить к ответу выше, как проверить, является ли проблема возврата каретки в Unix-подобной среде (я тестировал в MacOS)

1) Использование кошки

cat -e my_file_name

Если вы видите строки, оканчивающиеся на ^M$, то да, это проблема возврата каретки.

2) Найти первую строку с символом возврата каретки

grep -r $'\r' Grader.sh | head -1

3) Использование vim

vim my_file_name

Затем в VIM введите

:set ff

Если вы видите fileformat=dos, то файл fileformat=dos из среды dos, которая содержит возврат каретки.

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

Ответ 6

У меня была такая же проблема, когда я работал с Armbian Linux и Windows. Я пытался скопировать мои коды из Windows в Armbian, и когда я запускаю его, эта ошибка выскакивает. Моя проблема решена следующим образом: 1- попробуйте скопировать ваши файлы из окон с помощью WinSCP. 2- убедитесь, что в имени вашего файла нет символов()