case와 select는 코드 블럭을 반복해서 수행하지 않기 때문에 기술적으로 루프가 아닙니다. 하지만 루프가 하는 것처럼 특정 블럭의 위나 아래에서 주어진 조건에 따라 프로그램 흐름을 조정해 줍니다.
case는 C/C++의 switch와 동일합니다. 조건에 따라 여러개의 코드 블럭중 하나로 분기할 수 있게 해주는데, 여러개의 if/then/else의 간단한 표기법처럼 동작하기 때문에 메뉴같은 것을 만들 때 적당합니다.
case "$variable" in
"$condition1" )
command...
;;
"$condition2" )
command...
;;
esac
참고:
낱말 조각남(word splitting)이 일어나지 않기 때문에 꼭 variable을 쿼우팅 하지 않아도 됩니다.
각 조건들은 오른쪽 괄호, )로 끝납니다.
각 조건 블럭은 이중 세미콜론, ;;.
전체 case 블럭은 esac로 끝납니다(case를 거꾸로 스펠링).
예 10-22. case 쓰기
#!/bin/bash echo; echo "아무키나 누른 다음 리턴을 치세요." read Keypress case "$Keypress" in [a-z] ) echo "소문자";; [A-Z] ) echo "대문자";; [0-9] ) echo "숫자";; * ) echo "구두점이나, 공백문자 등등";; esac # [대괄호]속 범위의 문자들을 받아 들입니다. # 독자들용 연습문제: # 이 스크립트는 한개의 키누름만 받아들이고 종료합니다. # 이를 키가 눌릴때마다 무슨 키인지 계속 보여주면서 # 키가 "X"일 경우에만 종료하도록 고쳐보세요. # 힌트: "while"루프로 다 감싸면? exit 0 |
예 10-23. case로 메뉴 만들기
#!/bin/bash
# 조잡한 주소 데이타베이스
clear # 화면을 정리하고
echo " 주소록"
echo " ------"
echo "다음중 한 명을 고르세요:"
echo
echo "[E]vans, Roland"
echo "[J]ones, Mildred"
echo "[S]mith, Julie"
echo "[Z]ane, Morris"
echo
read person
case "$person" in
# 변수가 쿼우트 된 것에 주의하세요.
"E" | "e" )
# 대소문자 모두 인식.
echo
echo "Roland Evans"
echo "4321 Floppy Dr."
echo "Hardscrabble, CO 80753"
echo "(303) 734-9874"
echo "(303) 734-9892 fax"
echo "revans@zzy.net"
echo "Business partner & old friend"
;;
# 이중 세미콜론이 각 옵션을 끝내게 해 주는 것을 눈여겨 봐두세요.
"J" | "j" )
echo
echo "Mildred Jones"
echo "249 E. 7th St., Apt. 19"
echo "New York, NY 10009"
echo "(212) 533-2814"
echo "(212) 533-9972 fax"
echo "milliej@loisaida.com"
echo "Girlfriend"
echo "Birthday: Feb. 11"
;;
# Smith & Zane 은 나중에 추가.
* )
# 디폴트 옵션.
# 그냥 리턴을 쳐도 여기로 옵니다.
echo
echo "아직 등록이 안 돼 있습니다."
;;
esac
echo
# 독자용 연습문제:
# 입력을 한 번만 받고 끝내지 말고 계속 받을 수 있게 고쳐보세요.
exit 0 |
명령어줄 매개변수를 확인하려고 할 때, 아주 창의적인 방법으로 case를 사용하는 법을 보여 드리겠습니다.
#! /bin/bash
case "$1" in
"") echo "사용법: ${0##*/} <filename>"; exit 65;; # 명령어 줄 매개변수를 안 적었거나
# 첫번째 매개변수가 비어 있을 때
# ${0##*/} 는 매개변수 치환인 ${var##pattern} 이기 때문에 결과는 $0 이 됩니다.
-*) FILENAME=./$1;; # 첫번째 인자($1)인 filename이 대쉬(-)로 시작한다면
# ./$1 로 바꿉니다.
# 따라서, 다른 명령어들은 이것을 옵션으로 해석하지 못하게 됩니다.
* ) FILENAME=$1;; # 아무 것도 아니면, $1.
esac |
예 10-24. case용 변수를 만들기 위해서 명령어 치환 쓰기
#!/bin/bash # "case"용 변수를 만들기 위해서 명령어 치환 쓰기.. case $( arch ) in # "arch" 는 머신 아키텍쳐를 리턴합니다. i386 ) echo "80386 기반의 머신";; i486 ) echo "80486 기반의 머신";; i586 ) echo "Pentium 기반의 머신";; i686 ) echo "Pentium2+ 기반의 머신";; * ) echo "다른 형태의 머신";; esac exit 0 |
case는 globbing용 패턴으로 문자열을 필터링 할 수 있습니다.
예 10-25. 간단한 문자열 매칭
#!/bin/bash
# match-string.sh: 간단한 문자열 매칭
match_string ()
{
MATCH=0
NOMATCH=90
PARAMS=2 # 이 함수는 2개의 인자가 필요합니다.
BAD_PARAMS=91
[ $# -eq $PARAMS ] || return $BAD_PARAMS
case "$1" in
"$2") return $MATCH;;
* ) return $NOMATCH;;
esac
}
a=one
b=two
c=three
d=two
match_string $a # 잘못된 인자 갯수
echo $? # 91
match_string $a $b # 일치하지 않음
echo $? # 90
match_string $b $d # 일치함
echo $? # 0
exit 0 |
예 10-26. 입력이 알파벳인지 확인하기
#!/bin/bash
# 문자열을 필터링하기 위해서 "case" 구문 쓰기.
SUCCESS=0
FAILURE=-1
isalpha () # 입력 문자열의 "첫번째 문자"가 알파벳인지 아닌지 확인.
{
if [ -z "$1" ] # 인자 없이 넘어왔군.
then
return $FAILURE
fi
case "$1" in
[a-zA-Z]*) return $SUCCESS;; # 문자로 시작하는지.
* ) return $FAILURE;;
esac
} # C 의 "isalpha()" 함수와 비교해 보세요.
isalpha2 () # "문자열 전체"가 알파벳인지 확인.
{
[ $# -eq 1 ] || return $FAILURE
case $1 in
*[!a-zA-Z]*|"") return $FAILURE;;
*) return $SUCCESS;;
esac
}
check_var () # isalpha() 의 프론트엔드(front-end)
{
if isalpha "$@"
then
echo "$* = 알파벳"
else
echo "$* = 알파벳 아님" # 인자가 없어도 "알파벳 아님"임.
fi
}
a=23skidoo
b=H3llo
c=-What?
d=`echo $b` # 명령어 치환.
check_var $a
check_var $b
check_var $c
check_var $d
check_var # 인자없이 부르면 어떻게 될까요?
# S.C. 가 더 좋게 고침.
exit 0 |
select는 Korn 쉘에서 따온 것인데 메뉴를 만들때 쓸 수 있습니다.
select variable [in list]
do
command...
break
done
사용자가 list에 있는 것중 하나를 고를 수 있게 해 줍니다. 기본적으로 PS3(#? ) 프롬프트를 쓰고 이 값은 바꿀 수 있다는 것에 주의하기 바랍니다.
예 10-27. select로 메뉴 만들기
#!/bin/bash PS3='제일 좋아하는 야채를 고르세요: ' # 프롬프트 문자열 세트. echo select vegetable in "콩" "당근" "감자" "양파" "순무" do echo echo "제일 좋아하는 야채가 $vegetable 이네요." echo "깔깔~~" echo break # 여기에 'break'가 없으면 무한 루프를 돕니다. done exit 0 |
in list를 안 쓰면 select는 스크립트나 select를 포함하고 있는 함수로 넘어온 명령어 줄 인자($@)을 사용합니다.
in list가 빠졌을 경우를
for variable [in list]
의 경우와 비교해 보세요.예 10-28. 함수에서 select를 써서 메뉴 만들기
#!/bin/bash
PS3='제일 좋아하는 야채를 고르세요: '
echo
choice_of()
{
select vegetable
# select 에 [in list] 가 빠져있기 때문에, 함수로 넘어온 인자를 씁니다.
do
echo
echo "제일 좋아하는 야채가 $vegetable 군요."
echo "껄껄~~"
echo
break
done
}
choice_of 콩 쌀 당근 무 토마토 시금치
# $1 $2 $3 $4 $5 $6
# choice_of() 함수로 넘어갑니다.
exit 0 |