Bashスクリプト:ループ内で一度操作を実行し、停止してループし続けます。

Bashスクリプト:ループ内で一度操作を実行し、停止してループし続けます。

私のラップトップのバッテリーをチェックしてAndroid通知を送信するBashスクリプトがあります(Pushbullet APIへのcliインターフェースとして機能する私が書いたBashスクリプト、Shuttle経由)。うまくいきますが、バッテリーが100%に達すると、ラップトップを取り外すように警告が繰り返し表示されます。代わりに、100%の充電について一度だけ通知し、そのままにしておくことをお勧めします。ただし、バッテリーが不足しているときに繰り返し通知を送信すると、ノートパソコンを接続することを覚えています(現在はそうします)。

私はこれがループ内でcontinueとbreakコマンドを使用して実行できると思いますが、それが私が望むものであるかどうかはわかりません(私はこれについてよく知りません)。

とにかく、Bashを使ってこれを実装するための最良の方法の提案をいただきありがとうございます。これは簡単だと思いますが、何らかの理由で理解できません。

これは私のスクリプトです。

#! /bin/bash

while true;
do

percent=$(acpi | awk '{ print $4}' | sed -e 's/%//g' |  sed -e 's/,//g')

 if [ "$percent" -le "20" ];
then
    shuttle push note Chrome "Aurora: Plug in now" "Battery is at $percent percent"
fi  
if [ "$percent" -eq "100" ];
then
    shuttle push note Chrome "Aurora: Battery charged" "Battery is at $percent percent"
fi

sleep 7m
done

答え1

push(){
    shuttle push note Chrome \
        "Aurora: $1" \
        "Battery is at $percent percent"
}

full=0
while    percent=$(acpi | awk '{ print $4}' | sed 's/[,%]//g')
do       case $percent:$full in 
         (100:1) ;; (100:0)
              full=1
              push 'Battery charged';;
         (?:*|1?:*|20:*)
              full=0
              push 'Plug in Now';;
         (*1) full=0
         esac
done

シェルのcase文を使用すると、シェルパターンがシェル拡張値と一致するかどうかに応じて任意のコードブロックを実行できます。これにより、同じテストの複数の可能な結果を​​非常に簡単に処理できます。

$percent$full上記では、コロン区切り文字の値と値を連結しています:。この技術はもともとStephane Chazelasから学び、それ以来私自身もかなり上手になりました。実行されるコードは2つの値に依存するため、2つの値を同時にテストするのが最も簡単なソリューションです。

caseパターンブロックは、最初から最後まで順に評価されます。パターンが一致すると、そのコードが実行されてcase返されます。一致する最初のパターンは評価された最後のパターンでもあります。

$percentしたがって、値がそれぞれ次$fullの場合:

  1. 100と1

    • 空のコードブロックに関連付けられた最初のパターンが一致しました。何の処置も取らずcaseに戻りますwhile
  2. 100と0

    • 2番目のパターンが一致し、1に設定され、$fullシェル関数が引数で呼び出されます。pushBattery Charged
    • push()ここでは、目的に応じてコードを構築するためにのみ定義します。
  3. <= 20と何でも

    • 3番目のパターンマッチングは$full0に設定され、pushargとして呼び出されます。Plug in Now
  4. 何でも1

    • 最後のパターンが一致して$full0に設定されました。
  5. その他

    • 一致するパターンがなく、何もしません。

全体として$full、これは必要な場合にのみ設定され、push()0、100、または任意の値で<= 20の場合にのみ呼び出されることを意味します。$full$percent$full$percent

これらすべては、あなたがすでに持っているものよりも向上します。しかし、実際の質問は次のとおりです。

percent=$(acpi | awk '{ print $4}' | sed 's/[,%]//g')

while trueのように何度もフォークしてください。信じられないゴミ。別の方法を見つける必要があります。

答え2

どうですか?

if [ "$percent" -eq 100 ] && [ "$full_flag" -eq 0 ];
then
    shuttle push note Chrome "Aurora: Battery charged" "Battery is at $percent percent"
    full_flag=1
fi
if [ "$percent" -lt 100 ];
then
    full_flag=0
fi

答え3

continueループの次の繰り返しにジャンプします。breakループを完全に終了します。今後の反復に影響を与えたい場合は、どちらのアプローチも役に立ちません。これを行うには、何かが他の情報を表す必要があることを覚えておく必要があります。一部の情報を記憶する方法は、その情報を変数に保存することです。

必要なものを達成する1つの方法は、以前の値をpercent変数に保存することですpreviouspercentと両方がprevious100の場合、メッセージは印刷されません。

バッテリーを監視するためにバックグラウンドでこのプログラムを実行しているので、あまりにも多くの電力を使用しないようにしてください。プロセス数を最小限に抑えます。

繰り返すのではなく、trueコマンドを繰り返しますsleep。このようにして、sleepスクリプトの実行中(ほとんどの場合)killコマンドを使用してスクリプトを終了できます。

コードをインデントします。ブロック(など)内の項目は、do左側thenに空白が多く、一定量が必要です。

previous=
while sleep 7m
do
  percent=$(acpi | awk '{ gsub(/[^ 0-9]/, ""); print $4 }')
  if [ "$percent" -le "20" ]; then
    shuttle push note Chrome "Aurora: Plug in now" "Battery is at $percent percent"
  elif [ "$percent" -eq "100" ] && [ "$previous" -ne "100" ]; then
    shuttle push note Chrome "Aurora: Battery charged" "Battery is at $percent percent"
  fi
done

関連情報