Как сделать переменную из подоболочки доступной в родительской оболочке

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 час на поиски в Google без возможного решения в оболочке. я разочарован.
К кра
1
@ ToKra Нет. Ни один язык программирования не может сделать это. (Почти) любой язык программирования может передавать значение переменной из подпрограммы или блока инструкций в родительский элемент , и это именно то, что я объясняю в своем ответе: используйте группирование команд { … }вместо подоболочки ( … ).
Жиль "ТАК - перестань быть злым"
4

Товарищи по U & L: Прежде чем понизить мой ответ об использовании C-стиля с main()функцией, перейдите по этой ссылке: https://unix.stackexchange.com/a/313561/85039 Использование основных функций в сценариях - распространенная практика, используемая многими профессионалами. в поле.


Как указал Жиль, подоболочки не могут делать переменные доступными вне их среды. Но давайте подойдем к этой проблеме с другой стороны - если вы пишете свой скрипт в функциях, можно объявить переменную как localи которую можно редактировать.

Из руководства bash 4.3, localописание:

... Когда 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 расстаться?
Сергей Колодяжный,