bash - 선택 및 선택 실행 후 선택 메뉴를 다시 표시하는 방법

bash - 선택 및 선택 실행 후 선택 메뉴를 다시 표시하는 방법

업데이트 확인, 테마 재설치라는 두 가지 기능이 있는 테마용 도구 스크립트를 만들고 있습니다.

메뉴를 선택하는 코드는 다음과 같습니다.

PS3='Choose an option: '
options=("Check for update" "Reinstall theme")
select opt in "${options[@]}"
do
     case $opt in
             "Check for update")
                       echo "Checking update"
                               ;;
             "Reinstall theme")
                       echo "Reinstalling"
                               ;;
                               *) echo invalid option;;
     esac
done

실행할 때 이런 일이 발생합니다

1) Check for update
2) Reinstall theme
Choose an option:

1을 입력하고 Enter를 눌러 업데이트 명령 확인을 실행합니다.

문제는 스크립트 실행이 끝나면 메뉴 대신 "옵션 선택:"이 다시 표시된다는 것입니다. 따라서 메뉴가 없으면 사용자가 선택하기 어려울 수 있습니다(특히 매우 긴 스크립트 이후).

1) Check for update
2) Reinstall theme
Choose an option: 1
Checking update
Choose an option:

그러면 옵션을 실행한 후 메뉴를 다시 표시하려면 어떻게 해야 합니까?

답변1

나는 당신이 정말로 다음과 같은 것을 원하는 것 같아요 :

check_update () {
    echo "Checking update"
}

reinstall_theme () {
    echo "Reinstalling theme"
}

while true; do
    options=("Check for update" "Reinstall theme")

    echo "Choose an option:"
    select opt in "${options[@]}"; do
        case $REPLY in
            1) check_update; break ;;
            2) reinstall_theme; break ;;
            *) echo "What's that?" >&2
        esac
    done

    echo "Doing other things..."

    echo "Are we done?"
    select opt in "Yes" "No"; do
        case $REPLY in
            1) break 2 ;;
            2) break ;;
            *) echo "Look, it's a simple question..." >&2
        esac
    done
done

첫 번째 명령문을 더 작게 유지하기 위해 작업을 별도의 함수로 분할했습니다 case. 또한 문 $REPLY에서 옵션 문자열 대신 사용했습니다. 옵션 문자열 case이 더 짧고 변경하기로 결정했지만 두 곳에서 업데이트하는 것을 잊어버린 경우에도 깨지지 않기 때문입니다. 또한 스크립트의 후속 호출 PS3에 영향을 미칠 수 있으므로 건드리지 않기로 결정했습니다 . select다른 프롬프트를 원하면 한 번 설정하고 그대로 두겠습니다(아마도 PS3="Your choice: "). 이렇게 하면 여러 문제가 포함된 스크립트에 더욱 통일된 느낌을 줄 수 있습니다.

사용자가 작업을 완료할 때까지 모든 것을 반복하는 외부 루프를 추가했습니다. 첫 번째 문장의 질문을 다시 표시하려면 이 루프가 필요합니다 select.

그렇지 않으면 스크립트를 중단하는 것 외에는 종료할 수 있는 방법 breakcase없습니다.

a의 목적은 select실제로 스크립트의 메인 이벤트 루프(그 자체)가 되는 것이 아니라 사용자로부터 질문에 대한 답변을 얻는 것입니다. 일반적으로 a select-는 case실제로 변수를 설정하거나 함수를 호출하고 계속 진행해야 합니다.

첫 번째 버전에 "exit" 옵션이 포함된 더 짧은 버전 select:

check_update () {
    echo "Checking update"
}

reinstall_theme () {
    echo "Reinstalling theme"
}

while true; do
    options=("Check for update" "Reinstall theme" "Quit")

    echo "Choose an option: "
    select opt in "${options[@]}"; do
        case $REPLY in
            1) check_update; break ;;
            2) reinstall_theme; break ;;
            3) break 2 ;;
            *) echo "What's that?" >&2
        esac
    done
done

echo "Bye bye!"

답변2

do 루프는 무한하며 select 문은 그 외부에 있습니다. 스크립트는 select 문을 한 번 실행한 다음 do 루프 검사 케이스 $opt에 계속해서 머물러 있습니다. 내 제안은 다음과 같이 사례 설명 뒤에 중단을 추가하는 것입니다.

esac
break
done

그런 다음 전체 스크립트를 계속해서 반복하려면 select 문부터 did 문까지 모든 것을 포함하는 또 다른 루프를 만드세요.

답변3

나는 이 트릭을 사용합니다:

options=("First option" "Second option" "Quit")
PS3="So what? "
select opt in "${options[@]}"
do
    case $opt in
        "First option")
            echo "First option"
            ;;
        "Second option")
            echo "Second option"    
            ;;
        "Quit")
            echo "We are done..."
            break
            ;;
        *) 
            PS3="" # this hides the prompt
            echo asdf | select foo in "${options[@]}"; do break; done # dummy select 
            PS3="So what? " # this displays the common prompt
            ;;
    esac
done

답변4

내 방법을 확인할 수도 있습니다. 간단한 루프를 통해 function처리합니다.for

for((i=0;i<${#opt[@]};i++));do echo "$((i+1))) ${opt[$i]}";done

내 샘플 코드는 다음과 같습니다.

msg="Choose an option:"
opt=("Check_for_update" "Reinstall_theme")

refresh_the_list(){
echo -e "\n$msg"
for((i=0;i<${#opt[@]};i++))
do
        echo "$((i+1))) ${opt[$i]}"
done
}
echo $msg
select i in ${opt[@]}
do
        case $i in
                        ${opt[0]})
                                echo "Checking update"
                                refresh_the_list;;
                        ${opt[1]})
                                echo "Reinstalling"
                                refresh_the_list;;
                        *)
                                echo "invalid option"
                                refresh_the_list;;
        esac
done

관련 정보