Як зробити змінну з підшару, доступної в батьківській оболонці


11

Я написав швидкий і брудний сценарій, щоб підписати звіти з веб-служби:

BASE_URL='http://example.com/json/webservice/'
FIRST=1
FINAL=10000

for report_code in $(seq 1 $FINAL); do
  (time -p response=$(curl --write-out %{http_code} --silent -O ${BASE_URL}/${report_code}) ) 2> ${report_code}.time

  echo $response  # <------- this is out of scope!  How do I fix that?
  if [[ $response = '404' ]]; then
    echo "Deleting report # ${report_code}!"
    rm ${report_code}
  else
    echo "${report_code} seems to be good!"
  fi
done

Мені потрібно загортати timeкоманду в підзарядку, щоб я міг переспрямувати її вихід, але це робить значення $responseнедоступним для батьківської оболонки. Як мені подолати цю проблему?

Відповіді:


11

Ви не можете донести значення змінної з підзаголовка до її батьківського, не зробивши деяких схильних до помилок маршалінгу та громіздкого зв'язку.

На щастя, тут вам не потрібна передплата. Для перенаправлення потрібне лише групування команд з { … }, а не з підзарядкою.

{ time -p response=$(curl --write-out '%{http_code}' --silent -O "${BASE_URL}/${report_code}"); } 2> "${report_code}.time"

(Не забувайте подвійні лапки навколо змінних підстановок .)


смішно, що кожна мова програмування може це зробити. Я вже витратив 1 год на гуглінг без можливого рішення в оболонці. я знеохочений.
До

1
@ToKra Ні. Жодна мова програмування не може цього зробити. (Майже) будь-яка мова програмування може перенести значення змінної з підпрограми чи блоку інструкцій до її батьківського, і саме це я пояснюю у своїй відповіді: використовуйте групування команд { … }замість нижньої частини ( … ).
Жил "ТАК - перестань бути злим"

4

Користувачі, які користуються U&L: Перш ніж відмовитись від моєї відповіді на використання C-стилю з main()функцією, перейдіть за цим посиланням: https://unix.stackexchange.com/a/313561/85039 Використання основних функцій у сценаріях є звичайною практикою, яку використовують багато професіоналів в польових умовах.


Як підкреслив Жилл, підрозділи не можуть зробити змінні доступними поза їх оточенням. Але давайте підійдемо до цієї проблеми з іншого кута - якщо ви пишете свій скрипт у функціях, можна оголосити змінну такою, localяку можна редагувати.

З посібника bash 4.3, localопис:

... Коли локальна використовується у межах функції, вона призводить до того, що ім'я змінної має видимий обсяг, обмежений цією функцією та її дітьми ...

Приклад:

#!/bin/bash

outter()
{
    for i in $(seq 1 3)
    do
        var=$i
    done
}

main()
{
    local var=0
    outter
    echo $var
}
main "$@"
$ ./testscript.sh                                                                                                        
3

Як ви бачите, після 3 ітерацій циклічної функції змінна змінена.


Хм, неінтуїтивна поведінка для програмістів на С. Я, як правило, сподіваюся outterзвернутися до глобального екземпляра var.
Руслан

Ця відповідь має деякі недоліки. "$var"не потрібен у виклику outter. Це нічого не робить. А також local var=0нічого не робить; виклик ouf outterперезаписує var, як ви заявили.
Голар Рамблар

@GolarRamblar я видалив "$var"як позиційний аргумент outter; якщо бути справедливим, це поза звичкою. Чи можете ви детальніше local var=0 розібратися?
Сергій Колодяжний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.