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에게서 배웠고 그 이후로 나 자신도 꽤 능숙해졌습니다. 실행되는 코드는 두 값에 따라 달라지므로 두 값을 동시에 테스트하는 것이 가장 간단한 솔루션입니다.

case패턴 블록은 처음부터 마지막까지 순서대로 평가됩니다. 패턴이 일치하면 해당 코드가 실행되어 case반환됩니다. 일치하는 첫 번째 패턴은 평가된 마지막 패턴이기도 합니다.

$percent따라서 및 값이 각각 다음과 $full같은 경우:

  1. 100과 1

    • 빈 코드 블록과 연결된 첫 번째 패턴이 일치했습니다. 아무 조치도 취하지 않고 case로 돌아갑니다 while.
  2. 100과 0

    • 두 번째 패턴이 일치하고 1로 설정되며 $full쉘 함수가 인수와 함께 호출됩니다.pushBattery Charged
    • push()여기서는 목적에 따라 코드를 구성하기 위해서만 정의합니다.
  3. <=20 및 무엇이든

    • 세 번째 패턴 일치는 $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루프를 완전히 종료합니다. 향후 반복에 영향을 미치려는 경우에는 두 가지 접근 방식 모두 유용하지 않습니다. 이렇게 하려면 무언가가 다른 정보를 나타내야 한다는 것을 기억해야 합니다. 일부 정보를 기억하는 방법은 해당 정보를 변수에 저장하는 것입니다.

원하는 것을 달성하는 한 가지 방법은 의 이전 값을 percent변수에 저장하는 것입니다 previous. percent및 둘 다 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

관련 정보