Можно ли сохранить статус завершения последней команды ( $?
) без изменений после теста?
Например, я хотел бы сделать:
command -p sudo ...
[ $? -ne 1 ] && exit $?
Последний exit $?
должен возвращать статус выхода sudo, но вместо этого он всегда возвращает 0
(код завершения теста).
Возможно ли это сделать без временной переменной?
Еще один пример для уточнения:
spd-say "$@"
[ $? -ne 127 ] && exit $?
В этом случае я хочу выйти, только если найдена первая команда (код выхода! = 127
). И я хочу выйти с фактическим spd-say
кодом выхода (это не может быть
0
).
РЕДАКТИРОВАТЬ: я забыл упомянуть, что я предпочитаю решение жалоб POSIX для лучшей переносимости.
Я использую эту конструкцию в сценариях, где я хочу предоставить альтернативы для той же команды. Например, см. Мой скрипт crc32 .
Проблема с временными переменными заключается в том, что они могут скрывать другие переменные, и во избежание этого вы должны использовать длинные имена, что плохо для читабельности кода.
источник
if ! command -p sudo; then exit; fi
то же самое для вашего примера.[ $? -ne 127 ] && exit $?
)sudo
команда выполнена успешно (то есть, еслиsudo
завершается со статусом 0). Но в вашем коде сценарий продолжает работать (неsudo
завершается ), если это удаетсяcommand
а неsudo
на всех. Это то, что подразумевается под тем, что я хочу выйти, только если первая команда найдена (код выхода! = 127) и является указанным возвращением,command
когда вызываемая команда не найдена. Я предполагаю, что проблема в том, что вызов вsudo
качестве части теста позволяетsudo
подавить возвратcommand
в первую очередь и таким образом исказить тест.Ответы:
$_
будет работать в (по крайней мере) интерактивныйdash
,bash
,zsh
,ksh
(хотя , по- видимому , не в условном операторе по запросу) иmksh
снарядов. Из них - насколько мне известно - толькоbash
иzsh
будет также заполнять его в скриптовой оболочке. Это не параметр POSIX - он достаточно переносим для любой современной интерактивной оболочки.Для более портативного решения вы можете сделать:
Который в основном позволяет вам расширить начальное значение для
$?
хвоста скрипта, прежде чем даже проверять его значение в его начале .Но в любом случае, поскольку вы, похоже, проверяете,
sudo
можно ли найти команду в строке встроенного-p
переносимого пути оболочки с помощьюcommand
, я думаю, вы могли бы перейти к ней более прямо. Кроме того , просто чтобы быть ясно,command
не будет проверять на месте каких - либо аргументов вsudo
- так это толькоsudo
- и ничто не вызывает - что отношение к этому возвращаемого значения.И так или иначе, если это то, что вы пытаетесь сделать:
... отлично работает как тест, без каких-либо шансов на ошибки при выполнении команд,
sudo
возвращающихся таким образом, что это может исказить результаты вашего теста.источник
Существуют различные варианты надежной обработки состояния выхода без накладных расходов, в зависимости от фактических требований.
Вы можете сохранить статус выхода, используя переменную:
Вы можете напрямую проверить успех или неудачу:
Или используйте
case
конструкцию, чтобы дифференцировать статус выхода:с особым случаем, заданным в вопросе:
Все эти опции имеют то преимущество, что они соответствуют стандарту POSIX.
(Примечание. Для иллюстрации я использовал
echo
приведенные выше команды; замените их соответствующимиexit
операторами, чтобы они соответствовали запрошенной функции.)источник
("$(get_errnos)")
является искусственным добавлением подстановки команд, где в вопросе запрашивается сравнение с фактическими кодами ошибок, 2.) В стандарте ясно, что меняется$?
(и, следовательно, что не меняется), и 3.) там нет никаких побочных эффектов с этой конструкцией (если, как вы, вы вводите их без необходимости). - OTOH, так как вы не возражаете, другой ответ, который вы предпочитаете, явно нестандартный.$(get_errnos)
код к любым другим решениям (( exit 42 ); test "$(get_errnos)" -ne $? && echo $_
), они также не будут работать. (Вы предпочли ввести мое стандартное решение в несоответствие, а не другие нестандартные хаки .) - Конечно, вы можете добавить произвольный код к любым ответам и испортить его. - и WRT до смены$?
; только то, что вы не можете найти это, не означает, что это неправда. (Я уже предоставил в наших обсуждениях даже ключевые слова для поиска в POSIX.)zsh
(сначала упомянули в одиночку; позже вы также добавилиdash
), что я думаю, что это должно быть ошибкой, учитывая, что состояниеcase
выхода и настройки,$?
кажется, хорошо определены в POSIX. - А также здесь, опять же, вы применяете двойные стандарты; другой хак, например, не является ни стандартным, ни надежно работает в других стандартных оболочках (например, не вksh
). - Мои предложения стандартны и работаютbash
(в основном используются в Linux) иksh
(преобладающая оболочка в коммерческих Unixes).Использование
$_
, которое расширяется до последнего аргумента предыдущей команды.источник
$?
и и нет другой команды$_
. ИМХО, лучше придерживаться согласованного метода, который работает в других случаях (а также может помочь с читабельностью кода).case
паттернах , единственное место, которое имело бы значение в теории (но не в данном вопросе), является сконструированным случаем. - В любом случае, ваша подстановка команд оболочки будет распространяться на результат встроенной команды, обычно другие расширения не влияют на возвращаемое состояние в любом случае, если нет задействованных команд, которые могут создавать ошибки (случайныеx=${a!b}
ситуации, но не относящиеся к делу). - Что вы подразумеваете под «команда без имени команды» ?Вы можете определить (и использовать) функцию оболочки:
затем
Возможно, это «обман», так как он делает копию
$?
вcheck_exit_status
списке аргументов.Это может показаться немного неловким, и это так. (Это иногда случается, когда вы накладываете произвольные ограничения на проблемы.) Это может показаться негибким, но это не так. Вы можете сделать
check_exit_status
более сложным, добавив аргументы, которые сообщают ему, какие тесты нужно выполнить для значения состояния выхода.источник
Чтобы ответить на ваш прямой вопрос, нет, невозможно сохранить
$?
без изменений. И это один из тех случаев, когда я подозреваю, что вы сосредотачиваетесь не на той проблеме. Временная переменная является стандартным и предпочтительным способом получения эффекта, который вы ищете. Это настолько стандартно, что я бы предложил отказаться (или переосмыслить) любую причину, по которой, по вашему мнению, вы не хотите ее использовать; Я очень сомневаюсь, что это стоит дополнительной сложности, добавленной любым другим методом.Если вы просто спрашиваете из простого любопытства, тогда ответ - нет.
источник
$?
или что-то в этом роде?Вот мой фрагмент кода, чтобы сохранить предыдущий статус выхода без выхода из текущего скрипта / оболочки
источник