case 문
선택지가 여러 개일 때 if-elif-elif-elif...를 계속 늘어놓으면 코드가 금방 지저분해집니다. 이럴 때 case 문을 쓰면 훨씬 깔끔합니다. 변수 하나의 값에 따라 여러 경우를 처리할 때 case는 최적의 선택입니다.
기본 구문
case $변수 in 패턴1) # 패턴1에 맞을 때 실행 ;; 패턴2) # 패턴2에 맞을 때 실행 ;; *) # 어느 패턴에도 맞지 않을 때 실행 ;;esac
case는 esac로 닫습니다. 각 패턴은 ) 로 끝내고, 패턴 블록의 마지막에는 ;;를 붙입니다. *는 아무 패턴에도 맞지 않는 경우를 처리하는 기본값입니다.
패턴 매칭
|를 사용하면 여러 패턴을 OR로 묶을 수 있습니다.
case $answer in y|Y|yes|YES) echo "동의합니다." ;; n|N|no|NO) echo "거부합니다." ;; *) echo "알 수 없는 답변입니다." ;;esac
글로브 패턴도 사용할 수 있습니다.
case $filename in *.txt|*.md) echo "텍스트 파일" ;; *.sh) echo "쉘 스크립트" ;; *.py) echo "파이썬 스크립트" ;; *) echo "기타 파일" ;;esac
;; vs ;;& vs ;& 차이
세 가지 종결자가 있으며, 동작 방식이 다릅니다.
;; - 일반 종결. 해당 패턴 블록을 실행하고 case 문 전체를 빠져나갑니다. 가장 많이 사용합니다.
;;& - 다음 패턴도 검사합니다. 현재 블록 실행 후 아래 패턴들을 계속 검사해서 맞으면 실행합니다.
;& - 다음 블록을 무조건 실행합니다. 패턴 검사 없이 바로 아래 블록으로 이동합니다. C 언어의 fall-through와 비슷합니다.
value="hello"case $value in hello) echo "안녕하세요" ;;& # 다음 패턴도 검사 h*) echo "h로 시작합니다" ;; *) echo "기타" ;;esac
실행 결과는 다음과 같습니다.
안녕하세요
h로 시작합니다
hello가 첫 패턴에 맞아 실행된 뒤 ;;& 때문에 다음 패턴도 검사합니다. h*도 맞으므로 두 번째 블록도 실행됩니다.
실습 1. 메뉴 선택 스크립트
번호를 입력받아 동작을 선택하는 인터랙티브 메뉴 스크립트입니다.
#!/bin/bash# 새 파일: scripts/menu.shecho "============================="echo " 패키지 관리 메뉴"echo "============================="echo "1) 설치"echo "2) 삭제"echo "3) 업데이트"echo "q) 종료"echo "============================="echo -n "선택: "read choicecase $choice in 1) echo -n "설치할 패키지 이름: " read pkg echo "sudo apt install $pkg 실행 중..." ;; 2) echo -n "삭제할 패키지 이름: " read pkg echo "sudo apt remove $pkg 실행 중..." ;; 3) echo "패키지 목록 갱신 및 업그레이드 실행 중..." echo "sudo apt update && sudo apt upgrade" ;; q|Q) echo "종료합니다." exit 0 ;; *) echo "잘못된 선택입니다: '$choice'" exit 1 ;;esacecho "작업 완료."
실행 결과는 다음과 같습니다.
$ bash scripts/menu.sh
=============================
패키지 관리 메뉴
=============================
1) 설치
2) 삭제
3) 업데이트
q) 종료
=============================
선택: 1
설치할 패키지 이름: curl
sudo apt install curl 실행 중...
작업 완료.
$ bash scripts/menu.sh
선택: q
종료합니다.
실습 2. 파일 확장자별 처리 스크립트
파일 경로를 인자로 받아 확장자에 따라 다르게 처리합니다.
#!/bin/bash# 새 파일: scripts/file_handler.shfile="$1"if [[ -z "$file" ]]; then echo "사용법: $0 <파일경로>" exit 1fiif [[ ! -f "$file" ]]; then echo "오류: 파일이 없습니다 - $file" exit 1fiext="${file##*.}"case $ext in txt|md) echo "텍스트 파일입니다." echo "줄 수: $(wc -l < "$file")" echo "--- 내용 미리보기 ---" head -5 "$file" ;; sh) echo "쉘 스크립트입니다." echo "실행 권한 확인 중..." if [[ -x "$file" ]]; then echo "실행 권한이 있습니다." else echo "실행 권한이 없습니다. chmod +x $file 을 실행하세요." fi ;; py) echo "파이썬 스크립트입니다." python3 --version 2>/dev/null || echo "python3가 설치되지 않았습니다." echo "실행: python3 $file" ;; gz|tar|zip) echo "압축 파일입니다." echo "크기: $(du -sh "$file" | cut -f1)" ;; *) echo "알 수 없는 확장자입니다: .$ext" echo "파일 타입 확인: $(file "$file")" ;;esac
실행 결과는 다음과 같습니다.
$ bash scripts/file_handler.sh /etc/hostname
텍스트 파일입니다.
줄 수: 1
--- 내용 미리보기 ---
ubuntu
$ bash scripts/file_handler.sh scripts/menu.sh
쉘 스크립트입니다.
실행 권한 확인 중...
실행 권한이 없습니다. chmod +x scripts/menu.sh 을 실행하세요.
${file##*.}는 파일명에서 마지막 . 이후 문자열, 즉 확장자를 추출하는 매개변수 확장입니다. ##는 가장 긴 접두어를 제거하라는 의미입니다. 이 패턴은 PART 05에서 더 자세히 다룹니다.