Bash 脚本:在循环内做某事一次然后停止,但继续循环

And*_*eno 6 scripting notifications shell-script battery

我有一个 Bash 脚本,用于检查我的笔记本电脑电池并向我发送 Android 通知(通过 Shuttle,我编写的一个 Bash 脚本用作 Pushbullet API 的 cli 接口)。它运行良好,但当电池电量达到 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
Run Code Online (Sandbox Code Playgroud)

mik*_*erv 6

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
Run Code Online (Sandbox Code Playgroud)

shell 的case语句允许您根据 shell 模式是否可以与 shell 扩展的值匹配来执行任意代码块。通过这种方式,您可以非常简单地处理同一测试的多种可能结果。

上面我将$percent和的值连接到$full一个:冒号分隔符上,这是我最初从 Stephane Chazelas 那里学到的一种技术,即使我从那时起就已经非常擅长使用它。因为执行的代码需要依赖这两个值,所以同时测试这两个值是最简单的解决方案。

case模式块按从头到尾的顺序进行评估。一旦模式匹配,相关的代码就会被执行并case返回。第一个匹配的模式也是最后一个评估的模式。

因此,如果值$percent$full分别为:

  1. 100 和 1

    • 第一个模式被匹配,它与一个空代码块相关联。不采取任何行动,并case返回到while
  2. 100 和 0

    • 匹配第二个模式,它设置$full为 1 并调用push带有参数的 shell 函数Battery Charged
    • push() 在这里定义只是为了根据目的组织代码。
  3. <=20 和任何东西

    • 第三个模式匹配,$full设置为 0,并push使用 arg 调用Plug in Now
  4. 任何东西和 1

    • 最后一个模式匹配并$full设置为 0。
  5. 还要别的吗

    • 没有匹配的模式,也没有采取任何行动。

总而言之,这意味着$full仅在必要时设置,push()仅在$full为 0 且$percent为 100 或$full为任何值且$percent<= 20时调用。

所有这些都将是对你已有的改进。但真正的问题是:

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

在 a 中多次分叉while true非常浪费的。你必须想出另一种方法来做到这一点。


use*_*469 3

怎么样:

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
Run Code Online (Sandbox Code Playgroud)