在一个循环中,如何在语句为真时执行一次,再次为真时再执行一次?

In an loop, how do I execute a statement once when it is true, and then execute it again once when it is true again?

我一直在尝试为 15%、10% 和 5% 的电池通知制作一个脚本。当电池电量达到这些水平时,它会显示一条通知,提示我更换笔记本电脑。我创建了一个名为 运行Once 的变量来说明脚本是否已经执行了一次 if 语句。如果 运行Once 为假,运行 while 循环内的 if 语句,如果其中一个为真,则执行命令,然后将 运行Once 设置为真,停止 while -环形。但是,由于我需要循环整个代码,因此它还会将 运行Once 重置为 false。因此,如果电池电量仍然相同,它会重复执行这些命令。我尝试了不同的解决方案,但我不知道如何不让脚本将变量重置回 false。

while true; do
    battery=$(cat /sys/class/power_supply/BAT0/capacity)
    batteryStatus=$(cat /sys/class/power_supply/BAT0/status)
    runOnce=false

    if [ $batteryStatus != "Charging" ]; then
        while [ "$runOnce" = false ]; do
                runOnce=false
                if [ $battery -eq 15 ]; then
                        notify-send --urgency=critical "Low Battery! (15%)" "Charge your laptop quickly."
                        espeak "Low battery. Please charge."
                        runOnce=true
                elif [ $battery -eq 10 ]; then
                        notify-send --urgency=critical "Critical Battery! (10%)" "Charge your laptop now. Before you lose your data. Seriously."
                        espeak "Critical battery. Please charge."
                        runOnce=true
                elif [ $battery -eq 5 ]; then
                        notify-send --urgency=critical "REALLY Critical Battery! (5%)" "Dude, your battery is going to go to the landfill soon."
                        espeak "Critical battery. Charge immediately."
                        runOnce=true
                fi
        done
    fi

    sleep 5
done

你必须“记住状态”。您必须“记住”在循环“上方”运行 kind-of 之间电池处于什么状态。仅在状态发生变化时显示消息 - 当从正常电压变为低电压,或从低电压变为临界电压时。让我们做一些重构:

display_low() {
   notify-send --urgency=critical "Low Battery! (15%)" "Charge your laptop quickly."
    espeak "Low battery. Please charge."
}
display_crit() {
    notify-send --urgency=critical "Critical Battery! (10%)" "Charge your laptop now. Before you lose your data. Seriously."
    espeak "Critical battery. Please charge."
}
display_really_crit() {
    notify-send --urgency=critical "REALLY Critical Battery! (5%)" "Dude, your battery is going to go to the landfill soon."
    espeak "Critical battery. Charge immediately."
}

battery_to_state() {
   battery=
   # lets use bash syntax
   if (( battery <= 5 )); then
       echo really_crit
   elif (( battery <= 10 )); then
       echo crit
   elif (( battery <= 15 )); then
       echo low
   fi
   # if greater than 15, state is empty
}

laststate=
while true; do
    batteryStatus=$(cat /sys/class/power_supply/BAT0/status)
    battery=$(cat /sys/class/power_supply/BAT0/capacity)
    curstate=$(battery_to_state "$battery")
    if
       # Only display when not charging
       [[ "$batteryStatus" != "Charging" ]] &&
       # Only display if the state is not empty (below 15!)
       [[ -n "$curstate" ]] &&
       # Only display if the state __changed__!
       [[ "$laststate" != "$curstate" ]]
    then
       # jump to one of display_* functions, depending on state 
       "display_$curstate"
    fi
    laststate=$curstate
    #
    sleep 5
done