
Мне не обязательно нужен ответ, но если кто-то может указать мне на какую-то литературу или примеры, я бы хотел разобраться.
При запуске скрипта возникает ошибка:
Синтаксическая ошибка около неожиданного токена
fi
Я пришел к выводу, что проблема в моем if
утверждении, сделав if
комментарии к утверждениям и добавив, echo "$NAME"
которые отображают имена в /etc/
.
Когда я вношу изменения, удаляю #
from if
и fi
и добавляю #
to wc -c "$NAME"
, я получаю синтаксическую ошибку, которую я перечислил выше. Я добавил ;
между ]
then. Я также перешел then
на следующую строку без разрешения.
#!/bin/bash
for NAME in /etc/*
do
if [ -r "$NAME" -af "$NAME" ] then
wc -c "$NAME"
fi
done
решение1
Ключевые слова, такие как if
, then
, else
, fi
, for
, case
и т. д. должны находиться в том месте, где оболочка ожидает имя команды. В противном случае они рассматриваются как обычные слова. Например,
echo if
просто печатает if
, а не начинает условную инструкцию.
Таким образом, в строке
if [ -r "$NAME" -af "$NAME" ] then
слово then
является аргументом команды [
(на что она бы пожаловалась, если бы когда-нибудь ее запустили). Оболочка продолжает искать then
, и находит fi
в командной позиции. Поскольку есть , if
который все еще ищет свой then
, то fi
это неожиданно, это синтаксическая ошибка.
Вам нужно поставить перед ним разделитель команды, then
чтобы он был распознан как ключевое слово. Наиболее распространенным разделителем команды является перенос строки, но перед ним then
обычно используют точку с запятой (которая имеет точно такое же значение, как и перенос строки).
if [ -r "$NAME" -af "$NAME" ]; then
или
if [ -r "$NAME" -af "$NAME" ]
then
Как только вы это исправите, вы получите еще одну ошибку от команды, [
потому что она не понимает -af
. Вы, вероятно, имели в виду
if [ -r "$NAME" -a -f "$NAME" ]; then
Хотя тестовые команды выглядят как опции, вы не можете объединить их таким образом. Они являются операторами команды [
и должны быть отдельными словами (как [
и ]
).
Кстати, хотя [ -r "$NAME" -a -f "$NAME" ]
работает, я рекомендую писать либо
[ -r "$NAME" ] && [ -f "$NAME" ]
или
[[ -r $NAME && -f $NAME ]]
Лучше всего сохранять [ … ]
условные операторы простыми, поскольку [
команда не может легко отличить операторы от операнда. Если $NAME
выглядит как оператор и появляется в позиции, где оператор допустим, он может быть проанализирован как оператор. Этого не произойдет в простых случаях, рассмотренных в этом ответе, но более сложные случаи могут быть рискованными. Написание этого с отдельными вызовами [
и использование логических операторов оболочки позволяет избежать этой проблемы.
Второй синтаксис использует [[ … ]]
условную конструкцию, которая существует в bash (и ksh и zsh, но не в чистом sh). Эта конструкция является специальным синтаксисом, хотя [
разбирается как любая другая команда, поэтому вы можете использовать такие вещи, как &&
внутри, и вам не нужно заключать переменные в кавычки, за исключением аргументов некоторых строковых операторов ( =
, ==
, !=
, =~
) (см.Когда необходимо двойное кавычивание?для получения подробной информации).
решение2
Посмотрите, что изменилось:
если [ -r "$ИМЯ"-а -ф"$ИМЯ" ];затем # ^^^^^^ ^ wc -c "$ИМЯ" фи
Если вы хотите удалить все команды в блоке if, вам как минимум нужно добавить в него двоеточие, например:
if [ -r "$NAME" -a -f "$NAME" ]; then
:
fi
или однострочная версия
if [ -r "$NAME" -a -f "$NAME" ]; then :; fi
решение3
Другие уже указывали, но если вы ищете официальную ссылку, тоРТМ
если список; тогда список; [ elif список; тогда список; ] ... [ иначе список;] fi
Список if выполняется. Если его статус выхода равен нулю, выполняется список then. В противном случае каждый список elif выполняется по очереди, и если его статус выхода равен нулю, выполняется соответствующий список then, и команда завершается. В противном случае выполняется список else, если он присутствует. Статус выхода — это статус выхода последней выполненной команды или ноль, если ни одно из проверенных условий не является истинным.
Вам не хватает;
И синтаксис дляlist
описано вman test