Shell Script - синтаксична помилка поблизу несподіваного маркера `else '


15

Через наступний скрипт оболонки, чому я отримую помилки

syntax error near unexpected token `else'

Сценарій оболонки

echo "please enter username"
read user_name
echo "please enter password"
read -s pass
echo ${ORACLE_SID}
SID=${ORACLE_SID}
if ["${ORACLE_SID}" != 'Test'] then
sqlplus -s -l $USER_NAME/$PASS@$SID <<EOF
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
EOF
else
echo "Cannot copy"
fi


ви можете відредагувати рядок "копіювати з ....", оскільки він наразі показує щось, що ви не хочете показувати. (Однак, я сподіваюсь, що це вже модифіковані дані, оскільки вони були б дуже безпечними для безпеки)
Олів'є Дулак,

1
@OlivierDulac Якщо ви посилаєтесь на ім’я користувача та пароль у цьому рядку, вони відомі всім користувачам бази даних Oracle. Це поширена і добре відома з початку бази даних Oracle.
Йокоб

@OlivierDulac Запрошуємо вас, трохи інформації про це dba-oracle.com/t_scott_tiger.htm
Jcocob

Відповіді:


25

Ви повинні припинити такий стан if:

if [ "${ORACLE_SID}" != 'Test' ]; then

або так:

if [ "${ORACLE_SID}" != 'Test' ]
then

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

Причиною ;розриву або рядка є те, що умовна частина ifзаяви є лише командою. Будь-яка команда будь-якої довжини, щоб бути точним. Оболонка виконує цю команду, вивчає стан виходу команди і потім вирішує, виконувати thenчастину чи elseчастину.

Оскільки команда може бути будь-якої довжини, для позначення кінця частини умови має бути маркер. Це той ;чи новий рядок, за яким слід then.

Причина для пробілів після [- [це команда. Зазвичай вбудована оболонка. Оболонка виконує команду [з рештою як параметри, включаючи ]як обов'язковий останній параметр. Якщо ви не помістите пробіл після [оболонки, спробуєте виконати [whateverяк команду, так і не вдасться.

Причина для місця перед цим ]схожа. Тому що в іншому випадку він не буде розпізнаний як власний параметр.


Це було місце, однак тепер я отримую test.sh: line 6: [: missing ] ''
Йокоб

@lesmana. Хороший спосіб спочатку надати неправильну відповідь, а потім продовжуйте редагувати, перш ніж хтось надасть правильну відповідь. Будь ласка, спробуйте надати правильну відповідь з першого разу.
Валентин Байрамі

1
Я не вважаю свою першу відповідь неправильною. Насправді це було "місце на". Це просто не вирішило всіх проблем у питанні.
lesmana

if це синтаксис, це не звичайна команда. Це застережене слово. На відміну від багатьох інших мов програмування, оболонка не розпізнає зарезервовані слова скрізь, лише коли вони є першим словом команди (з кількома тонкощами).
Жиль "ТАК - перестань бути злим"

Дякуємо за роз’яснення. Я знаю, що ifце синтаксис. Я намагався повідомити, що умовна частина ifсинтаксису не обмежена певною формою. Я відредагував текст. Сподіваюся, зараз зрозуміліше.
lesmana

5

Ви можете легко перевірити свої сценарії оболонки, використовуючи ShellCheck в Інтернеті (також доступний як окремий інструмент).

У цьому випадку буде вказано, що оператору if потрібні пробіли після [і перед ], і що вам потрібен ;(або новий рядок) перед thenтим же рядком.

Коли ви виправите це, він продовжить повідомляти вам, що USER_NAMEвикористовується без ініціалізації ні до чого. Це тому, що у вас також є user_nameзмінна (справа має значення). Те саме стосується PASSі pass.

Він також говорить вам, щоб використовувати read -rдля зупинки readвід mangling \(це може бути важливо для паролів, наприклад), і що ви повинні подвоїти цитування змінних під час виклику, sqlplusщоб запобігти оболонці випадково робити ім'я файлу глобалізації та розбиття слів (знову це важливо, якщо наприклад, пароль містить символи, що містять файли, такі як *пробіли).

Відступ коду зробить його і більш читабельним:

#!/bin/bash

read -r -p 'please enter username: ' user_name
IFS= read -rs -p 'please enter password: ' pass

printf 'ORACLE_SID = %s\n' "$ORACLE_SID"
sid=$ORACLE_SID

if [ "$sid" = 'Test' ]; then
    echo 'Cannot copy' >&2
    exit 1
fi

sqlplus -s -l "$user_name/$pass@$sid" <<'SQL_END'
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
SQL_END

Тут я також дав можливість використовувати паролі з провідними або кінцевими символами пробілу, тимчасово встановивши IFSпорожній рядок для зчитування пароля read.

Логіка також була змінена, щоб врятувати, якщо $ORACLE_SID/ $sidє Test. Це дозволяє уникнути основної операційної частини сценарію у ifгілці.


Зауважте, що if ([ x = x ]) then (echo yes) fiтакож працює.
Стефан Шазелас

@ StéphaneChazelas Ага, так. І це може бути цікаво з точки зору програми, що генерує код оболонки, але це не так, як зазвичай пишуть ifзаяви з [ ... ]... :-)
Kusalananda

2

Під час написання shви хочете

if [ "$ORACLE_SID" != "Test" ]
then
  ...
fi

При написанні bash

if [[ "$ORACLE_SID" != "Test" ]]
then
  ...
fi

Зважайте на пробіли, будь ласка. Повинно бути пробілом між [[першим оператором.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.