iBetter Books
수정

select 메뉴

사용자가 여러 선택지 중 하나를 고르는 메뉴를 만들 때마다 번호를 직접 출력하고, 입력을 받고, 범위를 검사하는 코드를 매번 작성하는 것은 번거롭습니다. select는 이 과정을 자동화해줍니다. 항목 목록을 주면 번호를 붙여 출력하고, 선택을 받아 처리하는 루프를 만들어 줍니다.

기본 구문

select 변수 in 항목1 항목2 항목3; do    # 변수에 선택된 항목이 들어옴    # REPLY에 입력된 번호가 들어옴    break    # 또는 종료 조건done
select color in 빨강 초록 파랑 종료; do    echo "선택: $color (번호: $REPLY)"    breakdone

실행 결과는 다음과 같습니다.

1) 빨강
2) 초록
3) 파랑
4) 종료
#? 2
선택: 초록 (번호: 2)

select는 항목에 자동으로 번호를 붙여 출력합니다. #?가 기본 프롬프트입니다. 선택된 항목은 변수에, 입력된 번호는 $REPLY에 들어옵니다.

PS3로 프롬프트 변경

PS3 환경변수를 설정하면 #? 대신 원하는 프롬프트를 사용할 수 있습니다.

PS3="번호를 입력하세요: "select fruit in 사과 바나나 딸기 종료; do    case $fruit in        종료)            echo "종료합니다."            break            ;;        "")            echo "잘못된 번호입니다: $REPLY"            ;;        *)            echo "선택한 과일: $fruit"            ;;    esacdone

실행 결과는 다음과 같습니다.

1) 사과
2) 바나나
3) 딸기
4) 종료
번호를 입력하세요: 2
선택한 과일: 바나나
번호를 입력하세요: 9
잘못된 번호입니다: 9
번호를 입력하세요: 4
종료합니다.

잘못된 번호를 입력하면 변수가 빈 문자열이 됩니다. ""패턴으로 이 경우를 처리합니다.

select + case 조합

selectcase를 함께 쓰면 메뉴 기반 스크립트를 간결하게 만들 수 있습니다. select로 선택을 받고, case로 동작을 분기합니다.

실습. 서비스 관리 메뉴 스크립트

systemd 서비스를 관리하는 인터랙티브 메뉴 스크립트입니다.

#!/bin/bash# 새 파일: scripts/service_manager.shSERVICE="${1:-nginx}"echo "=============================="echo "  서비스 관리: $SERVICE"echo "=============================="PS3="동작을 선택하세요: "select action in "상태 확인" "시작" "중지" "재시작" "로그 보기" "종료"; do    case $action in        "상태 확인")            echo ""            echo "--- $SERVICE 상태 ---"            systemctl status "$SERVICE" 2>/dev/null || echo "(systemctl 사용 불가: 시뮬레이션 모드)"            echo ""            ;;        "시작")            echo ""            echo "sudo systemctl start $SERVICE"            echo "(실행하려면 sudo 권한이 필요합니다)"            echo ""            ;;        "중지")            echo ""            echo "sudo systemctl stop $SERVICE"            echo "(실행하려면 sudo 권한이 필요합니다)"            echo ""            ;;        "재시작")            echo ""            echo "sudo systemctl restart $SERVICE"            echo "(실행하려면 sudo 권한이 필요합니다)"            echo ""            ;;        "로그 보기")            echo ""            echo "--- 최근 로그 (20줄) ---"            journalctl -u "$SERVICE" -n 20 --no-pager 2>/dev/null || echo "(journalctl 사용 불가)"            echo ""            ;;        "종료")            echo "관리 메뉴를 종료합니다."            break            ;;        "")            echo "잘못된 선택입니다: '$REPLY'. 1-6 사이의 번호를 입력하세요."            ;;    esacdone

실행 결과는 다음과 같습니다.

$ bash scripts/service_manager.sh nginx
==============================
  서비스 관리: nginx
==============================
1) 상태 확인
2) 시작
3) 중지
4) 재시작
5) 로그 보기
6) 종료
동작을 선택하세요: 1

--- nginx 상태 ---
● nginx.service - A high performance web server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
   Active: active (running)

동작을 선택하세요: 7
잘못된 선택입니다: '7'. 1-6 사이의 번호를 입력하세요.
동작을 선택하세요: 6
관리 메뉴를 종료합니다.

select 루프는 break를 만나기 전까지 계속 메뉴를 표시합니다. 종료 항목을 선택하면 break로 루프를 빠져나옵니다.

select는 메뉴 항목이 배열에서 올 수도 있습니다. 동적으로 항목을 구성해야 한다면 배열을 사용합니다.

options=("설치" "삭제" "종료")select opt in "${options[@]}"; do    echo "선택: $opt"    [[ $opt == "종료" ]] && breakdone

배열은 PART 05에서 자세히 다루며, select와 조합하면 항목 수가 바뀌어도 코드 수정 없이 메뉴를 관리할 수 있습니다.