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

Обновлено: 08.07.2024

Вы когда-нибудь видели сообщение «синтаксическая ошибка рядом с неожиданным токеном» при запуске одного из ваших сценариев Bash?

В этом руководстве я покажу вам, почему возникает эта ошибка и как ее исправить.

Почему возникает синтаксическая ошибка неожиданного токена Bash?

Как следует из ошибки, это синтаксическая ошибка Bash, другими словами, она сообщает о неправильном синтаксисе где-то в вашем скрипте или команде. Есть много вещей, которые могут пойти не так в сценарии Bash и вызвать эту ошибку. Некоторыми распространенными причинами являются отсутствие пробелов рядом с командами и отсутствие экранирования символов, которые имеют особое значение для оболочки Bash.

Найти синтаксическую ошибку, о которой сообщается при выполнении скрипта, не всегда просто. Этот процесс часто требует многократного изменения и повторного тестирования сценария.

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

Начнем!

Один подход, чтобы все исправить

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

Не беспокойтесь об этом, главное, чтобы вы научились правильному подходу к определению причины ошибки и знали, как ее исправить.

Рассмотрев приведенные ниже примеры, вы узнаете, как это сделать.

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

В других примерах мы рассмотрим сценарии Bash, которые при выполнении завершаются с ошибкой «неожиданный токен».

Чтобы исправить ошибку в одной команде, обычно достаточно добавить или удалить несколько неправильных символов, вызывающих синтаксическую ошибку в команде.

Знание того, как исправить ошибку в скрипте, может занять немного больше времени, и для этого я буду использовать следующий пятиэтапный процесс:

  1. Запустите сценарий, содержащий синтаксическую ошибку.
  2. Обратите внимание на строку, упомянутую в ошибке Bash.
  3. Выполните строку с ошибкой в ​​оболочке Bash, чтобы быстро найти ошибку (без необходимости изменять сценарий и перезапускать его несколько раз).
  4. Обновите скрипт, указав правильную строку кода.
  5. Подтвердите, что скрипт работает.

Пришло время для первого сценария.

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

Допустим, в моей системе Linux есть следующий файл:

И я хочу переименовать его в report_july.csv.

Я могу использовать следующую команду, верно?

Когда я запускаю его, я получаю следующую ошибку:

Поскольку круглые скобки () используются в Bash для создания подоболочки. Другими словами, это специальные символы.

И специальный символ Bash необходимо экранировать, если он используется в команде как обычный символ. Обратная косая черта используется для экранирования символов.

Я обновлю команду, включив обратную косую черту перед обеими круглыми скобками:

На этот раз ошибок нет:

Урок 1. Не забывайте экранировать специальные символы Bash, когда вы используете их как обычные символы (литералы) в имени файла или строке вообще.

Первая ошибка исправлена!

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

А вот и второй сценарий.

Когда я запускаю следующий скрипт:

Я получаю следующую ошибку:

Вы видите, почему?

Ошибка вызвана отсутствием пробела между if и открывающей квадратной скобкой ( [ ).

И причина в следующем:

if — это встроенная команда оболочки, и вы можете подумать, что используете if здесь. Но на самом деле оболочка видит, что if[ это не известная команда оболочке.

В этот момент оболочка не знает, что делать, учитывая, что она не нашла if раньше, и останавливает скрипт с ошибкой, указанной выше.

Правильный сценарий:

Я только что добавил пробел между if и [, чтобы оболочка могла видеть команду if.

И вывод скрипта правильный:

Урок 2. Пробелы важны в Bash, чтобы помочь оболочке идентифицировать каждую команду.

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

При написании скриптов Bash, особенно в начале, часто случаются ошибки, подобные приведенной ниже:

Когда вы запускаете этот однострочный код, вот что вы получаете:

Давайте узнаем, почему…

Синтаксис цикла for в Bash:

И с помощью одной строки:

Итак, как вы можете видеть, точка с запятой используется в Bash для разделения команд, когда вы хотите написать их в одной строке.

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

Теперь вернемся к нашей ошибке…

Однострочник, вызвавший ошибку, содержит оператор then, который, как вы видите, не является частью структуры цикла for.

  • Синтаксическая ошибка.
  • Токен "тогда" неожиданный.

Давайте подтвердим, что после удаления однострочник работает нормально:

Урок 3. Если вы видите синтаксическую ошибку, убедитесь, что вы правильно используете циклы Bash или условные конструкции и не добавляете операторов, которых там быть не должно.

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

Я создал простой скрипт, в котором оператор if вложен в цикл while. Это очень распространено в Bash.

Этот скрипт может показаться нормальным, но когда я запускаю его, я получаю следующее…

Инструкции done и fi правильно используются для закрытия цикла while и условного оператора if. Но они используются в неправильном порядке!

Инструкция if вложена в цикл while, поэтому мы должны сначала закрыть оператор if, используя fi. И после этого мы можем закрыть цикл while с помощью done.

Давайте попробуем скрипт:

Урок 4. Вложенные циклы и условные операторы необходимо закрывать в том же порядке, в котором они открываются.

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

Давайте рассмотрим другой сценарий, в котором эта синтаксическая ошибка может возникнуть с токеном fi:

И вот что я получаю, когда запускаю его:

В этом случае оболочка Bash идентифицирует оператор if и поэтому ожидает его после него.

Как видите, тогда есть, так в чем проблема?

Между командой [ ] (да... это команда) и оператором then нет разделителя команд.

Итак, что исправить?

Добавьте разделитель команд сразу после закрывающей квадратной скобки. Мы будем использовать точку с запятой ( ; ) в качестве разделителя команд.

Наш скрипт становится:

И если я запущу его, я получу правильный вывод:

Урок 5. Не забудьте указать разделители команд в сценариях Bash. Либо точка с запятой, либо новая строка.

Заключение

Теперь у вас есть все необходимое, чтобы понять, что вызывает эту синтаксическую ошибку в ваших скриптах. Вы можете применить 5 уроков, которые я объяснил в этом руководстве, чтобы найти исправление.

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

Если у вас есть какие-либо вопросы, пожалуйста, напишите их в комментариях ниже.

Теперь предположим, что вы сохранили свой скрипт Bash с помощью Windows.

И когда вы запускаете его в Linux, вы видите синтаксическую ошибку, которую вы не можете объяснить, потому что скрипт кажется вам правильным.


Возможно, вы захотите отредактировать строку «копировать из .», так как в данный момент она может отображать что-то, что вы не хотите показывать. (Тем не менее, я надеюсь, что это уже измененная информация, так как это было бы очень плохо с точки зрения безопасности)

@OlivierDulac Если вы имеете в виду имя пользователя и пароль в этой строке, значит, они известны всем пользователям базы данных Oracle. Это распространено и хорошо известно с самого начала существования базы данных Oracle.

3 ответа 3

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

Примечание: вы также должны ставить пробелы после [ и перед] .

Причина ; или разрыв строки заключается в том, что часть условия оператора if является просто командой. Любая команда любой длины, если быть точным. Оболочка выполняет эту команду, проверяет статус выхода команды, а затем решает, выполнять ли часть then или часть else.

Поскольку длина команды может быть любой, для обозначения конца части условия необходим маркер. Это ; или новая строка, за которой следует then .

Причина пробелов после [ заключается в том, что [ — это команда. Обычно встроенный в оболочку. Оболочка выполняет команду [ с остальными параметрами, включая ] в качестве обязательного последнего параметра. Если вы не поставите пробел после [, оболочка попытается выполнить [любую команду и потерпит неудачу.

Причина пробела перед ] аналогична. Потому что иначе он не будет распознан как собственный параметр.

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

Я не считаю свой первый ответ неправильным. На самом деле это было «на месте». Это просто не решило все проблемы в вопросе.

если синтаксис is, это не обычная команда. Это зарезервированное слово. В отличие от многих других языков программирования, оболочка не везде распознает зарезервированные слова, а только в том случае, если они являются первым словом команды (с некоторыми тонкостями).

Спасибо за разъяснение. Я знаю, что если это синтаксис. Я пытался сообщить, что часть условия if не ограничена определенной формой синтаксиса. Я отредактировал текст. Надеюсь, теперь стало понятнее.

Вы можете легко проверить свои сценарии оболочки с помощью ShellCheck онлайн (также доступен как отдельный инструмент).

В этом случае будет указано, что оператору if нужны пробелы после [ и до ] и что вам нужен ; (или новую строку) перед then на той же строке.

Когда вы это исправите, он сообщит вам, что USER_NAME используется без какой-либо инициализации. Это потому, что у вас также есть переменная user_name (регистр имеет значение). То же самое верно для PASS и pass .

Он также говорит вам использовать read -r, чтобы остановить read от искажения \ (это может быть важно для паролей, например), и что вы должны использовать двойные кавычки для переменных при вызове sqlplus, чтобы предотвратить случайную подстановку имени файла оболочкой. и разделение слов (опять же, это важно, если пароль, например, содержит символы подстановки файлов, такие как * или пробелы).

Отступ в коде также сделает его более читабельным:

Здесь я также сделал возможным использование паролей с начальными или конечными пробелами, временно установив IFS на пустую строку для чтения пароля.

Также была изменена логика для выхода из строя, если $ORACLE_SID / $sid имеет значение Test . Это позволяет избежать размещения основной рабочей части скрипта в ветке if.

Синтаксическая ошибка сообщения об ошибке рядом с неожиданным токеном `(' возникает в среде типа Unix, Cygwin и в интерфейсе командной строки в Windows. Эта ошибка, скорее всего, будет вызвана при попытке запустить сценарий оболочки, который был отредактирован или создан в старых системах DOS/Windows или Mac.

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

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

Это сообщение об ошибке также появляется, когда вы вводите команды в командной строке Linux для повседневных задач, таких как копирование файлов вручную и т. д. Основные причины появления этого сообщения об ошибке – либо неправильный синтаксис, либо проблема ОС при интерпретации другого системные команды/оболочка.

Что вызывает синтаксическую ошибку рядом с неожиданным токеном `(‘?

  • Неверный синтаксис при выполнении любой команды на любой из платформ. Либо вы неправильно используете команду, либо ввели неверный синтаксис.
  • Оболочка несовместима с системами Unix/DOS.
  • Есть проблемы с запуском сценария оболочки bash из другого источника.

В этой статье мы предполагаем, что вы знакомы с основами программирования и имеете представление о том, что делаете. Если вы новичок, лучше всего следовать подробным руководствам по языку/команде, которую вы пытаетесь выполнить. Вероятно, вы допустили ошибку в синтаксисе.

Решение 1. Проверка синтаксиса и формата команд

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

Кроме того, следует уделить особое внимание дополнительному пробелу, использованию двойных кавычек и обязательным параметрам. Если какие-либо из них отсутствуют или были объявлены неправильно, вы не сможете выполнить свой код.

Например, вместо следующего кода

Вы должны выполнить его как

Кроме того, убедитесь, что вы правильно выполняете свои команды/скрипт оболочки, если он занимает несколько строк.

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

Решение 2. Устранение неполадок в сценарии оболочки

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

Попробуйте запустить оболочку с параметром «vx». Это покажет нам, какие команды выполняются и какие значения хранятся в сценарии. Здесь вы можете устранять неполадки и диагностировать, что происходит не так.

Например, выполните скрипт в терминале после включения «vx» как:

Вы можете проверить содержимое скрипта с помощью команды «cat» следующим образом:

Решение 3. Использование команды «dos2unix.exe»

В текстовых файлах Windows/DOS новая строка представляет собой комбинацию возврата каретки (\r) с последующим переводом строки (\n). В Mac (до Mac OS X) для разрыва строки использовался простой возврат каретки (\r). Unix/Linux и Mac OS X используют разрывы строк с переводом строки (\n). Если вы используете Cygwin, ему не удастся обработать сценарии, созданные в DOS/Windows и старых версиях Mac, из-за лишнего символа возврата каретки (\r).

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

С помощью команды «dos2unix.exe»

Здесь вы можете создать команду «dos2unix.exe», которая преобразует скрипт в правильный формат, после чего вы сможете без проблем выполнить его.

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

Текст был успешно обновлен, но возникли следующие ошибки:

francoism90 прокомментировал 15 февраля 2022 г.

@dancrossnyc Вы (также) используете ZSH? Переход на bash (снова) «исправил» проблему.

dancrossnyc прокомментировал 15 февраля 2022 г.

Я использую zsh; переход на bash хорош как временный обходной путь, но кажется далеко не идеальным.

francoism90 прокомментировал 15 февраля 2022 г.

@dancrossnyc Да, мне также нужно запустить ZSH, так как я использую плагины/псевдонимы. Надеюсь, эта проблема будет исправлена ​​в ближайшее время.

curoky прокомментировал 16 февраля 2022 г.

Неоднократно мучился с этой проблемой в течение последних двух дней и случайно обнаружил, что понижение версии до версии 0.70.0 может решить ее для меня.

image

tanhakabir прокомментировал 16 февраля 2022 г.

Исследуем это сейчас

tanhakabir прокомментировал 17 февраля 2022 г.

Это будет исправлено в завтрашнем предварительном выпуске после 8:00 по тихоокеанскому стандартному времени. Дайте мне знать, если это исправит это для всех вас.

dancrossnyc прокомментировал 18 февраля 2022 г.

Я изменил свою оболочку на своем компьютере с Linux обратно на zsh и перезапустил Code с сегодняшним утренним обновлением Remote, и, похоже, все снова работает. Спасибо за оперативность, @tanhakabir!

mic4ael прокомментировал 23 февраля 2022 г.

Я только что столкнулся с той же проблемой, и переход на предварительную версию решил проблему!

Прокомментировал Hasaber8 25 февраля 2022 г.

@tanhakabir Я переключился на предварительную версию, но меня все еще мучает та же проблема

Прокомментировал Hasaber8 25 февраля 2022 г.

@tanhakabir Я перешел на предварительную версию, но все еще сталкиваюсь с той же проблемой

Обновление:
Исправлено путем возврата к zsh в качестве оболочки по умолчанию

tanhakabir прокомментировал 25 февраля 2022 г.

@Hasaber8 ваша проблема выглядела иначе с Missing GLIBCXX >= 3.4.18! как ошибка

Прокомментировал Hasaber8 25 февраля 2022 г.

@Hasaber8 ваша проблема выглядела иначе с Missing GLIBCXX >= 3.4.18! как ошибка

на самом деле, я читал об этой проблеме, и кто-то предложил переключить оболочку по умолчанию на bash, что испортило ее, что фактически привело к указанной выше ошибке, я переключил ее обратно на zsh и bam, это сработало.

Прокомментировал Hasaber8 25 февраля 2022 г.

Что заставляет меня задаться вопросом, почему сейчас он не работает на bash + у меня есть эта версия модуля, который он запрашивает.

tanhakabir прокомментировал 25 февраля 2022 г.

@Hasaber8 Я не уверен, мы ничего не меняли для удаленных оболочек bash

Прокомментировал Hasaber8 25 февраля 2022 г.

@Hasaber8 Я не уверен, мы ничего не меняли для удаленных оболочек bash

Я постараюсь отладить и дам вам знать 😄

tanhakabir прокомментировал 25 февраля 2022 г.

@Hasaber8, вы могли бы попробовать использовать bash в качестве оболочки по умолчанию со старой версией расширения SSH и VS Code?

Прокомментировал Hasaber8 25 февраля 2022 г.

Конечно, попробую

andodeki прокомментировал 1 марта 2022 г. •

@Hasaber8, вы сталкивались с той же проблемой?

tanhakabir прокомментировал 1 марта 2022 г.

@andodeki, вы можете создать отдельную задачу со своим полным журналом, и я смогу вам помочь!

Читайте также: