[: Неожиданный оператор в программировании оболочки

159

Мой код:

    #!/bin/sh
    #filename:choose.sh
    read choose
    [ "$choose" == "y" -o "$choose" == "Y" ] && echo "Yes" && exit 0
    [ "$choose" == "n" -o "$choose" == "N" ] && echo "No"  && exit 0
    echo "Wrong Input" && exit 0

Но когда я выполняю

    sh ./choose.sh

сообщите мне, что

   [: 4: n: :Unexpected operator
   [: 5: n: :Unexpected operator

Есть ли ошибка в моем bash script? Спасибо!

  • 0
    Когда я выполнил один и тот же код в Linux и в Cygwin, я не получил никаких ошибок
  • 2
    Cygwin, скорее всего, связал sh с bash . В некоторых дистрибутивах больше нет настоящего sh . Хотя некоторые будут утверждать (и я склонен согласиться), что если вы пишете скрипт для переносимости, пишите его в sh вместо bash .
Показать ещё 2 комментария
Теги:

8 ответов

260
Лучший ответ

В вашем bash script нет ошибки. Но вы выполняете его с sh, который имеет менее обширный синтаксис;)

Итак, запустите bash ./choose.sh вместо:)

  • 3
    Решите мою проблему. Спасибо! Тогда есть ли разница между командами "sh" и "bash"?
  • 3
    Синтаксис bash - это расширенный набор синтаксиса sh - исполняемый файл /bin/sh в вашей системе может предоставлять только стандартные функции sh , в которые не включены тесты в стиле [] .
Показать ещё 13 комментариев
227

POSIX sh не понимает == для равенства строк, так как это bash -ism. Вместо этого используйте =.

Другие люди, говорящие, что скобки не поддерживаются sh, неверны, btw.

  • 4
    Да, я пытаюсь просто заменить "==" на "=", сценарий также может быть исполнительным: "sh ./choose.sh". Оба bash и sh поддерживают скобки.
  • 39
    +1 Это лучший ответ, чем ненужное использование bash, IMO.
Показать ещё 2 комментария
23

В вашем коде замените эту строку:

#!/bin/sh

с

#!/bin/bash

Это должна быть первая строка вашего скрипта и указывает, какую оболочку linux нужно использовать. sh не поддерживает те же команды, что и bash.

И тогда вы можете вызвать ваш скрипт напрямую (он должен быть исполняемым):

./choose.sh

или с

bash ./choose.sh

sh не будет работать, так как это bash-скрипт. Ответ от Ницше будет работать с ш.

5

вы можете использовать case/esac вместо if/else

case "$choose" in
  [yY]) echo "Yes" && exit;;
  [nN]) echo "No" && exit;;
  * ) echo "wrong input" && exit;;
esac
5

вместо этого вы должны использовать bash или переписать script с помощью стандартного sh

sh -c 'test "$choose" = "y" -o "$choose" = "Y"'
  • 0
    Я думаю, что удобнее использовать «[]» вместо «тест». Казалось, что "bash ./choose.sh" может решить проблему.
  • 0
    @kit в любом случае, sh более компактен
Показать ещё 1 комментарий
3

Чтобы выполнить его с помощью Bash, используйте #!/bin/bash и chmod для его выполнения, затем используйте

./choose.sh
2

Фактически "квадратная открывающая скобка" - это всего лишь внутренний псевдоним оболочки для тестовой команды.

Итак, вы можете сказать:

test -f "/bin/bash" && echo "This system has a bash shell"

или

[ -f "/bin/bash" ] && echo "This system has a bash shell"

... они эквивалентны либо sh, либо bash. Обратите внимание на требование наличия закрывающей "]" скобки в команде "[", но кроме этого "[" совпадает с "тестом" ). "тест человека" - хорошая вещь для чтения.

  • 0
    man test - это справочная страница / bin / test, а не встроенной функции оболочки
  • 0
    ls $(which [) дает /usr/bin/[
-2

Не используйте зарезервированное ключевое слово в качестве начала любого имени переменной: например HOSTNAME завершится неудачно, поскольку HOST {TYPE | NAME} зарезервированы

Ещё вопросы

Сообщество Overcoder
Наверх
Меню