親シェルでサブシェルの変数を使用できるようにする方法


11

私は、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

timeコマンドをサブシェルでラップして、その出力をリダイレクトできるようにする必要がありますが、これにより、の値が$response親シェルで使用できなくなります。この問題を回避するにはどうすればよいですか?

回答:


11

変数の値をサブシェルからその親に渡すことはできません。エラーが発生しやすいマーシャリングと面倒な通信を行わなければ、それができません。

幸い、ここにはサブシェルは必要ありません。リダイレクションには、サブシェルではなく、によるコマンドのグループ化のみが必要{ … }です。

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

変数置換を囲む二重引用符を忘れないでください。)


面白いのは、すべてのプログラミング言語でそれができることです。私はすでにシェルで可能な解決策なしで1時間グーグルを過ごしました。私はがっかりした。
2016

1
@ToKraいいえ。これを実行できるプログラミング言語はありません。(ほぼ)どのプログラミング言語でも、サブルーチンまたは命令ブロックからその親に変数の値をもたらすことができます。それは、私が答えで説明するとおりです。{ … }サブシェルの代わりにコマンドグループを使用します( … )
Gilles「SO-邪悪なことをやめなさい」

4

フェローU&Lのユーザー:とCスタイルを使用するための私の答えをdownvoting前にmain()機能、このリンクをご覧ください。https://unix.stackexchange.com/a/313561/85039をスクリプトで主な機能を使用すると、多くの専門家によって使用される一般的な方法であり、現場で。


Gillesが指摘したように、サブシェルは環境外で変数を使用可能にすることはできません。しかし、別の角度からこの問題に取り組みましょう-関数でスクリプトを書く場合、変数をasとして宣言する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回繰り返した後にわかるように、変数は変更されています。


うーん、Cプログラマにとっては直感的でない動作です。通常outter、のグローバルインスタンスを参照することを期待しますvar
ルスラン

この回答にはいくつかの欠陥があります。"$var"コールアウトでは必要ありませんoutter。何もしません。また、local var=0何もしません。あなたが述べたように、呼び出しouf outterはを上書きvarします。
Golar Ramblar

@GolarRamblarへの"$var"位置引数として削除しましたoutter。公平に言うと、これは癖です。local var=0 一部について詳しく説明していただけますか?
Sergiy Kolodyazhnyy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.