web-dev-qa-db-ja.com

Zenityプログレスバーは変数に影響しますか

こんにちは皆さん、現在whileループにzenityプログレスバーを実装しようとしていますが、増分されるはずの変数が増分されないことに気付きました。これが私が試したサンプルのテストスクリプトです。

i=0
p=0

while [ $i -lt 10 ]
do
      i=$[$i + 1]
      echo $i
      p=$[$p + 1]
done | (zenity --progress --title="test" --text="test")
echo "i: $i p: $p"

プログレスバーが機能していることに気付きましたが、カウンターとして使用される変数pは、Zenityの影響を受けました。私のコードに何か問題がありますか?変数iはプログレスバーを移動するために値をエコーするためのもので、変数pは他の目的のためのものです。 piの値は、whileループ内でインクリメントしても、両方とも0です。

Zenityプログレスバーを削除せずに変数piをインクリメントする方法があることを望んでいます。しかし、(zenity --progress --title="test" --text="test")行が削除された後に変数の増分が機能する理由はわかりません。

追加

進行状況バーが終了した後に変数iおよびpを使用する方法は?もう1つの質問は、whileループを()で囲む必要がありますか?

助けてくれてありがとう!

2
pikachu

インクリメントとすべてがまったく問題ないようです。ただし、すべての増分は、zenityに渡されるサブシェル内で行われます。これが、サブシェルの外部でecho変更を取得しても変更を取得できない理由です。私はあなたのスクリプトを使用していますが、変数を印刷するものを追加するだけでdo whilezenityポップアップウィンドウでループします。 Zenity Progressダイアログの構文の詳細については、 gnomeヘルプページ を参照してください。以下のスクリプトを実行して結果を確認します。

#!/bin/bash
i=0
p=0
(while [ $i -lt 100 ]
do
    i=$[$i + 10]
    echo $i ; sleep 1
    echo "#  now i is $i and p=$p"
    p=$[$p + 1]
done) | zenity --progress --title="test" --text="test"
echo "i: $i p: $p"

iの増分を10に変更し、iを使用してプログレスバーの増分を作成し、sleep 1進行を知覚できるようにします。

Observation:値はzenityポップアップで増加することが示されていますが。端末上で変更されていないことを示しています、i: 0 p: 0

the zenity window

これが役立つことを願っています。

サブシェル変数を外部で使用する方法

親シェルは、サブシェルの変数を使用できません。 サブシェルの詳細はこちら を見つけることができます。しかし、サブシェルから一時ファイルに変数を書き込み、その親が読み取ることができます。最高の方法ではないかもしれませんが、機能します。

#!/bin/bash
..
(while [ $i -lt 100 ]
do
    ...
    ...
done
echo "p=$(echo $p)" > tmp
echo "i=$(echo $i)" >> tmp
) | zenity --progress --title="test" --text="test"
. tmp
rm tmp
echo "i: $i p: $p"

これで、端末にi: 100 p: 10ので、あなたの希望に応じてそれらを使用します。そして、あなたが最後の部分で尋ねたように、それはwhileループではなく、サブシェルです。サブシェルの内容を括弧で囲むのが習慣です。

3
souravc

プロセス置換は、迷惑なサブシェルの作成を防ぐことができますが、構文は少し奇妙です:

$ k=0; for x in a b; do ((k++)); done | zenity --progress; echo "$k"

→0(OKではない)

$ k=0; for x in a b; do ((k++)); done > >(zenity --progress); echo "$k"

→2(OK)

私が気に入っているのは、通常、スクリプトを適切に機能させるためにスクリプトを大幅に変更する必要がないことです。ただし、一部のエキゾチックなシェルにはこの機能が欠けている場合があります。 Bashについては、マニュアルの「Process Substitution」セクションを確認してください。

最初の質問の例により近いコードで:

  i=0
  p=0

  while [ $i -lt 10 ]
  do
        i=$[$i + 1]
        echo $((10 * i))
        sleep 0.1
        p=$[$p + 1]
  done > >(zenity --progress --title="test" --text="test")
  echo "i: $i p: $p"

(スリープを追加して進行をより目立たせ、iを10回エコーして100ループの終わりに達したとき。)

1
Alice M.