Como fazer uma variável de um subshell disponível no shell pai

9

Eu escrevi um script rápido e sujo para cronometrar alguns relatórios de um serviço da Web:

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

Eu preciso envolver o comando time em um subshell para que eu possa redirecionar sua saída, mas isso torna o valor de $response indisponível para o shell pai. Como contornar este problema?

    
por iconoclast 01.07.2014 / 00:44

2 respostas

10

Você não pode trazer o valor de uma variável de um subshell para seu pai, não sem fazer uma comunicação predisposta a erros e incômoda.

Felizmente, você não precisa de uma subshell aqui. O redirecionamento requer apenas o agrupamento de comandos com { … } , não um subnível.

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

(Não se esqueça de aspas duplas em torno das substituições de variáveis .

    
por 01.07.2014 / 01:10
4

Fellow U & L usuários: Antes downvoting minha resposta para usar o estilo C com main() função, por favor visite este link: link O uso de funções principais em scripts é uma prática comum, usada por muitos profissionais da área.

Como Gilles apontou, as subshells não podem disponibilizar variáveis fora de seu ambiente. Mas vamos abordar esse problema de outro ângulo - se você escrever seu script em funções, é possível declarar a variável como local e isso pode ser editado.

Do manual do bash 4.3, local description:

...When local is used within a function, it causes the variable name to have a visible scope restricted to that function and its children...

Exemplo:

#!/bin/bash

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

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

Como você pode ver depois de 3 iterações da função looping, a variável é modificada.

    
por 17.01.2017 / 07:36