Как использовать case/esac в подстановке процесса?

У меня есть следующая строка, которая отлично работает:

while getopts :t t; do case $t in t) echo $t; break; esac; done

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

Код:

#!/usr/bin/env bash
echo $BASH_VERSION
[ "$(while getopts :t t; do case $t in t) echo $t; break; esac; done)" = "t" ] && echo "Option specified."

Результат:

$ ./test.sh -a -b -c -t
4.3.42(1)-release
./test.sh: line 3: unexpected EOF while looking for matching `"'
./test.sh: line 4: syntax error: unexpected end of file

Обратная косая черта \) в t) не помогает. И синтаксис (t) работает в GNU bash 3.2.57, но не в 4.3.42.

Кажется, что использование обратных кавычек отлично работает для обеих версий:

[ "`while getopts :t t; do case $t in t) echo $t; break; esac; done`" = "t" ] && echo "Option specified."

однако я не хочу использовать этот синтаксис, поскольку он устарел.

Как я могу использовать синтаксис case в приведенной выше подстановке команд ($())?

Или, может быть, есть другой способ сделать то же самое?

В основном, чтобы проверить, был ли указан параметр -t для сценария, и выполнить какую-либо команду, если это так.


person kenorb    schedule 28.12.2015    source источник


Ответы (2)


Если у вас есть версия bash, в которой сканер был сломан таким образом, что завершался только при несбалансированном ) — ошибка, которой больше нет в текущей версии 4.3 — вы можете обойти ее следующим образом:

#!/usr/bin/env bash
[ "$(while getopts :t t; do case $t in (t) echo $t; break;; esac; done)" = "t" ] && echo "Option specified."

Ключевое отличие здесь заключается в использовании (t), а не t), в результате чего скобки уравновешиваются. Это синтаксис, явно разрешенный в стандарте POSIX sh.

person Charles Duffy    schedule 29.12.2015
comment
Вы уверены, что протестировали первое решение с 3.2.57? В этой версии у меня работает только ваше второе решение. - person Julian; 29.12.2015
comment
Ваша первая строка вашего ответа неверна - согласно ссылке, которую вы предоставляете в конце своего ответа, The ;; является необязательным для последнего составного списка. - person Julian; 29.12.2015
comment
Ох; Я использую #!/usr/bin/env shebang, который поставил бы 4.3 на первое место в моем пути; вы правы, это ошибка с моей стороны. - person Charles Duffy; 29.12.2015
comment
Если ;; необязателен для последнего компаунд-листа и при смешивании (t) с break; (без ;;) все равно ломается на 4.3.42, но работает на 3.2.57, значит моя версия все еще глючит? Однако он работает с (t) и break;;. - person kenorb; 29.12.2015

Однако чего вы пытаетесь достичь? Скорее всего, можно избежать [ ... ] и подстановки команд. Возможно, это то, что вы ищете:

while getopts :t t; do
  case $t in t) true; break;; *) false;; esac
done && echo Yes || echo No

Статус выхода цикла while — это статус выхода оператора case. Нет необходимости оборачивать это в [, чтобы проверить, верно это или нет, что в любом случае часто является антипаттерном.

person tripleee    schedule 29.12.2015