Вы когда-нибудь видели сообщение «Ошибка синтаксиса рядом с неожиданным токеном» при запуске одного из ваших скриптов Bash?
В этом руководстве я покажу вам, почему возникает эта ошибка и как ее исправить.
«Bash Syntax Error Near Unexpected Token» — это ошибка синтаксиса Bash, которая сообщает о неправильном синтаксисе в вашем скрипте или команде. В скрипте Bash может быть много ошибок, которые могут привести к этой ошибке. Некоторые распространенные причины — отсутствие пробелов рядом с командами и отсутствие экранирования для символов, имеющих особое значение для оболочки Bash.
Поиск синтаксической ошибки, сообщаемой при выполнении скрипта, не всегда прост. Этот процесс часто требует многократного изменения и повторного тестирования скрипта.
Чтобы облегчить вам жизнь, я проанализировал различные сценарии, в которых может возникнуть эта синтаксическая ошибка. Для каждого сценария я покажу вам скрипт или команду с ошибкой и исправление, которое вам нужно применить для решения проблемы.
Один подход к исправлению этой ошибки в нескольких сценариях
Изучив приведенные ниже примеры, вы узнаете, как определить причину этой ошибки и как ее исправить.
В некоторых примерах я покажу вам, как исправить эту ошибку, если она возникает при выполнении одной команды в оболочке Bash.
В других примерах мы рассмотрим скрипты Bash, выполнение которых завершается ошибкой «unexpected token».
Чтобы исправить ошибку в одной команде, обычно достаточно добавить или удалить несколько неверных символов, вызывающих синтаксическую ошибку в команде.
Чтобы понять, как исправить ошибку в скрипте, может потребоваться немного больше времени, и для этого я буду использовать следующий процесс из 5 шагов:
- Запустите скрипт, содержащий синтаксическую ошибку.
- Обратите внимание на строку, упомянутую в ошибке Bash.
- Выполните строку с ошибкой в оболочке Bash, чтобы быстро найти ошибку (без необходимости изменять скрипт и перезапускать его несколько раз).
- Обновите свой скрипт, добавив правильную строку кода.
- Подтвердите, что скрипт работает.
Давайте рассмотрим первый сценарий.
Syntax Error Near Unexpected Token ‘(‘
Допустим, в моей системе Linux есть следующий файл:
-rw-r--r-- 1 ec2-user ec2-user 28 Jun 28 22:29 report(july).csv
И я хочу переименовать его в report_july.csv.
Я могу использовать следующую команду, верно?
mv report(july).csv report_july.csv
При запуске появляется следующая ошибка:
-bash: syntax error near unexpected token `('
Но почему?
Потому что скобки () используются в Bash для создания подоболочки. Другими словами, это специальные символы.
А специальные символы Bash необходимо экранировать, если они используются как обычные символы в команде. Обратная косая черта используется для экранирования символов.
Я обновлю команду, включив обратную косую черту перед обеими скобками:
mv report\(july\).csv report_july.csv
На этот раз ошибок нет:
-rw-r--r-- 1 ec2-user ec2-user 28 Jun 28 22:29 report_july.csv
Урок 1: Не забывайте экранировать специальные символы Bash, когда вы используете их как обычные символы (литералы) в имени файла или строке в целом.
Мы исправили первую ошибку!
Syntax Error Near Unexpected Token Then (Пример 1)
А вот и второй сценарий.
Когда я запускаю следующий скрипт:
#!/bin/bash
DAY="Monday"
if[ $DAY == "Monday" ]; then
echo "Today is Monday"
else
echo "Today is not Monday"
fi
Я получаю следующую ошибку:
(localhost)$./unexpected_token.sh
./unexpected_token.sh: line 5: syntax error near unexpected token `then'
./unexpected_token.sh: line 5: `if[ $DAY == "Monday" ]; then'
Понимаете почему?
Ошибка вызвана отсутствием пробела между if и открывающейся квадратной скобкой ([).
Причина в следующем:
if — встроенная команда оболочки, и вы можете подумать, что используете if здесь. Но на самом деле оболочка видит if[, что это не известная ей команда.
Оболочка не знает, как с этим справиться, поскольку она не нашла его ранее, и останавливает скрипт с ошибкой, указанной выше.
Правильный сценарий:
#!/bin/bash
DAY="Monday"
if [ $DAY == "Monday" ]; then
echo "Today is Monday"
else
echo "Today is not Monday"
fi
Я только что добавил пробел между if и [, чтобы оболочка могла видеть команду if.
Вывод скрипта правильный:
(localhost)$./unexpected_token.sh
Today is Monday
Урок 2: Пробелы важны в Bash, поскольку они помогают оболочке идентифицировать каждую команду.
Syntax Error Near Unexpected Token Then (Пример 2)
При написании скриптов Bash, особенно в начале, часто можно допустить ошибки, подобные приведенной ниже:
(localhost)$ for i in {0..10} ; do echo $i ; then echo "Printing next number" ; done
Вот что вы получите, если запустите этот однострочный код:
-bash: syntax error near unexpected token `then'
Давайте выясним почему.
Синтаксис цикла for в Bash:
for VARIABLE in {0..10}
do
echo command1
echo command2
echo commandN
done
И используя одну строку:
for VARIABLE in {0..10}; do echo command1; echo command2; echo commandN; done
Итак, как вы можете видеть, точка с запятой используется в Bash для разделения команд, когда вы хотите записать их в одну строку.
Причина, по которой точки с запятой не требовались в первой версии скрипта, заключается в том, что символ новой строки также является разделителем команд.
Теперь вернемся к нашей ошибке…
Однострочник, который завершался ошибкой, содержит оператор then, который, как вы видите, не является частью структуры цикла for.
Ошибка сообщает нам:
- Синтаксическая ошибка.
- Знак «then» является неожиданным.
Давайте убедимся, что однострочный код работает нормально после удаления:
(localhost)$ for i in {0..10} ; do echo $i ; echo "Printing next number" ; done
0
Printing next number
1
Printing next number
2
Printing next number
3
Printing next number
4
Printing next number
5
Printing next number
6
Printing next number
7
Printing next number
8
Printing next number
9
Printing next number
10
Printing next number
Работает!
Урок 3: Если вы видите синтаксическую ошибку, проверьте, правильно ли вы используете циклы Bash или условные конструкции и не добавляете ли вы какие-либо операторы, которых там быть не должно.
Syntax Error Near Unexpected Token Done
Я создал простой скрипт, в котором оператор if вложен в цикл while. Это очень распространено в Bash.
#!/bin/bash
COUNTER=0
while true
do
if [ $COUNTER -eq 0 ]; then
echo "Stopping the script..."
exit 1
done
fi
Этот скрипт может показаться нормальным, но когда я его запускаю, я получаю следующее:
./unexpected_token.sh: line 8: syntax error near unexpected token `done'
./unexpected_token.sh: line 8: ` done'
Почему?
Операторы done и fi правильно используются для закрытия цикла while и условного оператора if. Но они используются в неправильном порядке!
Оператор if вложен в цикл while, поэтому сначала мы должны закрыть оператор if, используя fi. А после этого мы можем закрыть цикл while, используя done.
Давайте попробуем сценарий:
(localhost)$./unexpected_token.sh
Stopping the script...
Теперь все хорошо.
Урок 4: Вложенные циклы и условные операторы необходимо закрывать в том же порядке, в котором они открываются.
Syntax Error Near Unexpected Token fi
Давайте рассмотрим другой сценарий, в котором эта синтаксическая ошибка может возникнуть с токеном fi:
#!/bin/bash
for NAME in 'John' 'Mark' 'Kate'
do
if [ "$NAME" == 'Mark' ] then
echo 'Hello Mark!'
fi
done
И вот что вы получите, если запустите его:
./unexpected_token.sh: line 7: syntax error near unexpected token `fi'
./unexpected_token.sh: line 7: ` fi'
В этом случае оболочка Bash распознает оператор if и поэтому ожидает после него then.
Как видите, так и есть, так в чем проблема?
Между командой [ ] (да… это команда) и оператором then нет разделителя команд.
Так в чем же решение?
Добавьте разделитель команд сразу после закрывающей квадратной скобки. Мы будем использовать точку с запятой (;) в качестве разделителя команд.
Наш сценарий становится таким:
#!/bin/bash
for NAME in 'John' 'Mark' 'Kate'
do
if [ "$NAME" == 'Mark' ]; then
echo 'Hello Mark!'
fi
done
И если я его запущу, то получу правильный вывод:
(localhost)$./unexpected_token.sh
Hello Mark!
Урок 5: Не забудьте указать разделители команд в скриптах Bash. Либо точка с запятой, либо новая строка.
Заключение
Теперь у вас есть все, что нужно, чтобы понять, что вызывает эту синтаксическую ошибку в ваших скриптах. Вы можете применить 5 уроков, которые я объяснил в этом руководстве, чтобы найти исправление.
Если у вас есть вопросы, пожалуйста, оставьте комментарий ниже.
Теперь предположим, что вы сохранили свой Bash-скрипт с помощью Windows.
А когда вы запускаете его в Linux, вы видите синтаксическую ошибку, которую не можете объяснить, поскольку скрипт выглядит для вас правильным.