Jak udostępnić zmienną z podpowłoki w powłoce nadrzędnej

11

Napisałem szybki i brudny skrypt, aby sprawdzić czas niektórych raportów z serwisu internetowego:

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

Muszę zawinąć timepolecenie w podpowłokę, aby móc przekierować jego dane wyjściowe, ale to sprawia, że ​​wartość $responseniedostępna dla powłoki nadrzędnej. Jak obejść ten problem?

ikonoklasta
źródło

Odpowiedzi:

11

Nie można przenieść wartości zmiennej z podpowłoki do jej rodzica, nie bez podatnego na błędy gromadzenia i uciążliwej komunikacji.

Na szczęście nie potrzebujesz tutaj podpowłoki. Przekierowanie wymaga tylko grupowania poleceń za pomocą { … }, a nie podpowłoki.

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

(Nie zapomnij o podwójnych cudzysłowach wokół podstawień zmiennych ).

Gilles „SO- przestań być zły”
źródło
to zabawne, że każdy język programowania może to zrobić. Spędziłem już 1 godzinę na googlowaniu bez żadnego możliwego rozwiązania w powłoce. jestem rozczarowany.
Do Kra
1
@ToKra Nie. Żaden język programowania nie może tego zrobić. (Prawie) każdy język programowania może przynieść wartość zmiennej z podprogramu lub bloku instrukcji do swojego rodzica, i dokładnie to wyjaśniam w mojej odpowiedzi: użyj grupowania poleceń { … }zamiast podpowłoki ( … ).
Gilles „SO- przestań być zły”
4

Inni użytkownicy U&L: Przed zanegowaniem mojej odpowiedzi dotyczącej używania stylu C z main()funkcją, proszę odwiedzić ten link: https://unix.stackexchange.com/a/313561/85039 Używanie głównych funkcji w skryptach jest powszechną praktyką stosowaną przez wielu profesjonalistów na polu.


Jak zauważył Gilles, podpowłoki nie mogą udostępniać zmiennych poza środowiskiem. Podejdźmy jednak do tego problemu z innej strony - jeśli napiszesz skrypt w funkcjach, localmożesz zadeklarować zmienną jako i można ją edytować.

W podręczniku bash 4.3 localopis:

... Kiedy lokalny jest używany w funkcji, powoduje, że nazwa zmiennej ma widoczny zasięg ograniczony do tej funkcji i jej dzieci ...

Przykład:

#!/bin/bash

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

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

Jak widać po 3 iteracjach funkcji zapętlania, zmienna jest modyfikowana.

Sergiy Kolodyazhnyy
źródło
Hmm, nieintuicyjne zachowanie programistów C. Normalnie spodziewałbym outtersię, że będę odnosił się do globalnego wystąpieniavar .
Ruslan
Ta odpowiedź ma pewne wady. "$var"nie jest potrzebne w wywołaniu outter. Nic nie robi. A także local var=0nic nie robi; funkcja połączenia outterzastępujevar , jak powiedziałeś.
Golar Ramblar
@GolarRamblar Usunąłem "$var" jako argument pozycyjny outter; szczerze mówiąc, to jest z przyzwyczajenia. Czy możesz opracować co do local var=0 części?
Sergiy Kolodyazhnyy