Призначення вихідного коду локальній змінній оболонки


Відповіді:


58

local t1=$(exit 1) повідомляє оболонці:

  • запустити exit 1в передпласті;
  • зберігає свій вихід (як і текст, який він виводить на стандартний вихід) у змінній t1, локальній для функції.

Таким чином, нормально, що в t1кінцевому підсумку залишається порожнім.

( $()відомий як підміна команд .)

Код виходу завжди призначається $?, так що ви можете зробити

function0()
{
  (exit 1)
  echo "$?"
}

щоб отримати ефект, який ви шукаєте. Звичайно, ви можете призначити $?іншу змінну:

function0()
{
  (exit 1)
  local t1=$?
  echo "$t1"
}

1
Ви знаєте, ви також завжди можете покласти повернення в трубу. `$ (trap 'printf" :: ERRNO: $? "' 0; # тепер зробіть все, що завгодно - ця пастка забезпечить, щоб остання записана рядок була останньою віддачею для всього контексту заміни.
mikeserv

1
@mikeserv Ви пропустили тестування? $(trap 'printf "::ERRNO:$?"' 0; # now do whatever however
Doktor J

12

Код виходу зберігався в $? змінна. Використовуючи Command Substitution лише захоплюючи вихід, вам слід скористатися (...) для створення нижньої оболонки :

#!/bin/bash

func() {
  (exit 1)
  local t1=$?
  printf '%d\n' "$t1"
}

func

сенс завдання t1=$?- використовувати його, ні? і не хотілося б $?розібратися в дорученні оп? Напевно, я запитую, чи не повинно бути цьогоprintf '%d\n' "${t1}"
Dani_l

@Dani_l: Дякую, це помилкова помилка. Оновлено.
cuonglm

Зауважте, що командна заміна лише фіксує стандарт, якщо не буде перенаправлено інакше.
фіат

7

У bashцьому працює:

loc(){  local   "x=$(exit "$1"):$?"
        printf  '$%s:\t%d\n' \
                 x "${x##*:}" \? "$?"
}

Це пов'язано з порядком оцінки команд та призначенням змінних. localмає власне значення повернення - і це команда, що виконується в даний час, а не підміна команди. З тієї причини, як ...

x=$(exit 1); echo "$?"

... може повернути 1, тому що ніколи не відбувається повернення в цій команді, за винятком запуску нижньої оболонки для присвоєння $xзначення - тому $?не стає халобером, як це відбувається практично у кожному іншому випадку, коли використовуються підстановки команд.

У всякому разі, з localйого дійсно затертий , - але якщо ви ловите його в потрібний час - що в той час розкладання все ще оцінюються і перш , ніж local процедури «s є шанс побити його - ви можете призначити його.

unset x; loc 130; echo "${x-\$x is unset}"

... відбитки ...

$x: 130
$?: 0
$x is unset

Ви повинні знати, що в багатьох оболонках ви не можете розраховувати на $?те, що таким чином встановите середину оцінки. Насправді, це, мабуть, тому, що ці снаряди не намагаються переоцінювати на кожному можливому етапі, як це можливо bash, - що, я б стверджував, це, мабуть, краща поведінка, ніж поведінка bash. Ви дійсно хочете, щоб ваш інтерпретатор рекурсивно оцінював циклічні значення, які, швидше за все, будуть перезаписані раніше, ніж у вас буде можливість їх використовувати?

У всякому разі, саме так ви можете це зробити.


-1

Залежно від того, чому ви намагаєтеся просто отримати код виходу, ви також можете просто запустити, if some-command; then echo "Success $?"; else echo "Failure $?"; fiякий нічого не робить з результатом команди, він просто оцінює код виходу запуску команди. Ви можете додати or( or$ ( around the command and you'll still get the same results. A better example might beякщо grep -q 'somestring' деякий файл; потім відлуння "Знайдено код виходу з рядка $?"; Інше "Не знайшли код виходу з рядка $?"; Fi`.

Ви також можете перевірити код повернення функції, яка може бути або явним, return 3або неявним кодом повернення, який є результатом останньої команди, і в цьому випадку потрібно бути обережним, щоб у вас не було echoкінця функція, інакше вона маскує / скидає попередній вихідний код.

command_last () {
  echo "True is `true`"
  echo "False is `false`"
  false
}
command_last; echo $?
# Outputs:
# True is 0
# False is 1
# 1

echo_last () {
  echo "True is `true`"
  echo "False is `false`"
  false
  # echo'ing literally anything (or nothing) returns true aka exit 0
  echo
}
echo_last; echo $?
# Outputs:
# True is 0
# False is 1
#            # Blank line due to empty echo
# 0

Нарешті, брудний трюк, оскільки ви не можете цього зробити, VAR=(SOME_COMMAND)тому що VAR=()це визначення масиву, тому вам потрібно VAR=( $(echo 'Some value') ).


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