Shell Script
Shell Script란?
- 셸 스크립트(shell script)는 셸이나 명령 줄 인터프리터에서 돌아가도록 작성되었거나 한 운영 체제를 위해 쓰인 스크립트
- 단순한 도메인 고유 언어로 여기기도 함
- 셸 스크립트가 수행하는 일반 기능으로는 파일 이용, 프로그램 실행, 문자열 출력 등이 있음
.sh
라는 파일 확장자를 가진 파일이 특정 종류의 셸 스크립트를 가리키는 것이 보통이지만, 대부분의 셸 스크립트는 파일 확장자를 지니지 않음
Shell Script 장단점
장점
- 셸 스크립트를 기록하는 것은 다른 프로그래밍 언어의 같은 코드로 쓰인 것보다 훨씬 더 빠른 경우가 많음
- 다른 해석 언어에 비해, 셸 스크립트는 컴파일 단계가 없기 때문에 스크립트는 디버깅을 하는 동안 빠르게 실행할 수 있음
단점
- 셸 스크립트를 사용함으로써 몇 가지 중대한 단점이 존재
- 실행되는 각 명령에 대한 잠재적으로 새로운 하부 프로세스의 수많은 필요에 따라 속도가 느려질 수 있음
- 단순 sh 스크립트는 다양한 종류의 유닉스, 리눅스, BSD 운영 체제, therof 버전, 시스템 유틸리티와 잘 호환된다는 장점이 있지만 더 복잡한 셸 스크립트는 셸, 유틸리티, 다른 필수 요소 간의 약간의 차이가 많은 경우 실패할 가능성이 있음
- 이와 비슷하게, 더 많은 복잡한 스크립트들은 셸 스크립트 언어 자체의 제한 안에서 실행할 수 있음
- 이러한 제한 때문에 다양한 셸이 문제를 개선할 목적으로 고품질의 코드와 확장을 기록하기 힘들 수 있음
Shell Script 기초
기본 설정
#!/bin/sh
echo "Hello, World!"
- 셸 스크립트 파일은 기본적으로
.sh
확장자로 작성
- 실제 코드를 작성하기 전에 맨 처음의 행에는
#!/bin/sh
를 씀
- 시스템에 지금부터 셸 스크립트를 쓴다는 사실을 알려주기 위함
#
는 hash, !
는 bang이므로 #!
를 shebang이라고 부르기도 함
- bash의 독자적인 기능을 사용하는 경우 다르게 작성
- 셸 스크립트 파일(
test.sh
)를 실행하기 위해서는, 터미널에서 파일이 저장된 장소에 가서 아래의 커맨드 중 하나를 선택해서 실행해야 함
$ chmod 755 test.sh
$ ./test.sh
$ sh test.sh
$ bash test.sh
- 파일을 실행시키면, 작성한
Hello, World!
가 표시됨
기본 커맨드
#!/bin/sh
echo "Hello, World!"
입력 / 출력
#!/bin/sh
read NAME
echo "Hello, $NAME!"
>>> $ ./test.sh
>>> Hwaya
>>> Hello, Hwaya!
- 입력을 대기하고 있는 경우, 스크립트는 실행되지 않음
- Bash에서는
-e
플래그로 특수 텍스트를 이스케이프 할 수 있음
#!/bin/bash
echo -e "Hello\n$NAME!"
변수
- 변수의 이름으로써 영문자, 숫자, 그리고 언더바가 사용됨
- 변수에 값을 전달할 때는
=
의 앞,뒤에 공백 없이 작성
- 변수에 액세스할 때 변수명의 앞에
$
를 넣거나 혹은 $
넣어서 변수를 {}
로 감쌈
- 하나의 변수에 한 개의 값만 보존됨
- 변수의 값이 덮어 쓰기되는 것을 방지하기 위해서는
readonly
를 사용
- 변수를
unset
으로 삭제할 수 있음
#!/bin/sh
var="변수1"
VaR_2="변수2"
echo "Var_2=$VaR_2"
VaR_2="VaR_2 변경"
echo ${VaR_2}
readonly var
var="readonly var 변경 불가능"
>>> $ ./test.sh
>>> Var_2=변수2
>>> VaR_2 변경
>>> shell.sh: line 11: var: readonly variable
특별한 변수
$0
: 스크립트명
$1
~ $9
: 인수, 첫 번째의 인수는 $1
, 2번째 인수는 $2
로 액세스
$#
: 스크립트에 전달된 인수의 수
$*
: 모든 인수를 모아 하나로 처리
$@
: 모든 인수를 각각 처리
$?
: 직전에 실행한 커맨드의 종료 값(0은 성공, 1은 실패)
$$
: 이 쉘 스크립트의 프로세스 ID
$!
: 마지막으로 실행한 백그라운드 프로세스 ID
#!/bin/sh
echo "\$0(스크립트 명): $0"
echo "\$1(1번째 인수): $1"
echo "\$2(2번째 인수): $2"
echo "\$3(3번째 인수): $3"
echo "\$#(인수의 수): $#"
echo "\"\$*\": \"$*\""
echo "\"\$@\": \"$@\""
VAR="마지막 값은 0!"
echo $?
>>> $ ./test.sh first second 3rd
>>> $0(스크립트 명): test.sh
>>> $1(1번째 인수): first
>>> $2(2번째 인수): second
>>> $3(3번째 인수): third
>>> $#(인수의 수): 3
>>> "$*": "first second third"
>>> "$@": "first second third"
>>> 0
특수 문자
* ? [ ' " ` \ $ ; & ( ) | ~ < > # % = 스페이트 탭 개행
은 쉘 스크립트의 특수 문자
- 문자열로써 사용할 때는
\
를 앞에 쓴 다음에 사용
변수 값의 치환
${var}
: 변수 값을 바꿔 넣음
${var:-word}
: 변수가 아직 세팅되지 않거나 공백 문자열의 경우 word를 반환, var에는 저장되지 않음
${var:=word}
: 변수가 아직 세팅되지 않거나 공백 문자열의 word를 반환, var에 저장
${var:?word}
: 변수가 아직 세팅되지 않거나 공백 문자열의 경우 치환에 실패하고 스탠다드 에러에 에러가 표시됨
${var:+word}
: 변수가 세팅되지 않은 경우 word가 반환, var에는 저장되지 않음
#!/bin/sh
echo "1 - ${var:-wordSetInEcho1}"
echo "2 - var = ${var}"
echo "3 - ${var:=wordSetInEcho3}"
echo "4 - var = ${var}"
unset var
echo "5 - ${var:+wordSetInEcho5}"
echo "6 - var = $var"
var="newVarValue"
echo "7 - ${var:+wordSetInEcho7}"
echo "8 - var = $var"
echo "9 - ${var:?StandardErrorMessage}"
echo "10 - var = ${var}"
>>> 1 - wordSetInEcho1
>>> 2 - var =
>>> 3 - wordSetInEcho3
>>> 4 - var = wordSetInEcho3
>>> 5 -
>>> 6 - var =
>>> 7 - wordSetInEcho7
>>> 8 - var = newVarValue
>>> 9 - newVarValue
>>> 10 - var = newVarValue
배열 (Bash)
#!/bin/bash
ARRAY=(item1 item2 item3 item4)
ARRAY[0]="ITEM1"
ARRAY[2]="ITEM3"
echo "ARRAY[0]: ${ARRAY[0]}"
echo "ARRAY[1]: ${ARRAY[1]}"
echo "ARRAY[*]: ${ARRAY[*]}"
echo "ARRAY[@]: ${ARRAY[@]}"
>>> $ ./test.sh
>>> ARRAY[0]: ITEM1
>>> ARRAY[1]: item2
>>> ARRAY[*]: ITEM1 item2 ITEM3 item4
>>> ARRAY[@]: ITEM1 item2 ITEM3 item4
오퍼레이터
- 셸에서는 산수 연산자로
expr 숫자 연산자 숫자
를 이용한다.
- 연산자
+
: 덧셈
-
: 뺄셈
\*
: 제곱
echo expr 11 \* 11
>>> 121
/
: 나눗셈
%
: 나머지
=
: 저정
==
: 동일
[ "$a" == "$b" ]
$a
과 $b
가 동일하는 경우 TRUE가 반환
!=
: 다름
[ "$a" != "$b" ]
$a
과 $b
가 동일하지 않는 경우 TRUE가 반환
- 비교
eq
: 동일
[ "$a" -eq "$b" ]
$a
와 $b
가 동일한 경우 TRUE가 반환
-ne
: 다름
[ "$a" -ne "$b" ]
$a
와 $b
가 동일하지 않은 경우 TRUE가 반환
-gt
: 보다 큼
[ "$a" -gt "$b" ]
$a
가 $b
보다 큰 경우 TRUE가 반환
-lt
: 보다 작음
[ "$a" -lt "$b" ]
$a
가 $b
보다 작은 경우 TRUE가 반환
-ge
: 보다 크거나 같음
[ "$a" -ge "$b" ]
$a
가 $b
보다 크거나 같은 경우 TRUE가 반환
-le
보다 작거나 같음
[ "$a" -le "$b" ]
$a
가 $b
보다 작거나 같은 경우 TRUE가 반환
!
: 아님
[ ! "$a" -gt "$b" ]
$a
가 $b
보다 크지 않은 경우 TRUE가 반환
-o
: 어느 쪽이든 (OR)
[ "$a" -gt "$b" -o "$a" -lt "$b" ]
$a
가 $b
보다 크거나 작은 경우 TRUE가 반환
- Bash 확장 / POSIX 폐지 예정
-a
: 양쪽 모두 (AND)
[ "$a" -gt 90 -a "$a" -lt 100 ]
$a
가 90보다 크고 100보다는 작은 경우 TRUE가 반환
-z
: 문자열이 비었는가
[ -z "$a" ]
$a
에 어떤 것도 지정되지 않은 경우 TRUE가 반환
-n
: 문자열이 차있는가
[ -n "$a" ]
$a
에 어떠한 것이 지정되어 있다면 TRUE가 반환
if 조건
- if의 기본 작성법은
if [ 조건 ] then 커맨드 fi
임
- 조건과 일치하는 경우,
then
뒤의 커맨드가 실행
- 조건과 다른 경우, 차례로
elif [ 조건 ]
에 적힌 내용을 확인
- 일치하는 조건이 없는 경우,
else
다음의 커맨드가 실행된 후 종료
else
가 존재하지 않는 경우, 그대로 종료됨
#!/bin/sh
if [ "$1" -gt "$2" ]
then
echo "1번째 인수가 2번째 인수보다 크다"
elif [ "$1" -eq "$2" ]
then
echo "1번째 인수와 2번째 인수가 동일하다"
else
echo "1번째 인수가 2번째 인수보다 작다"
fi
>>> $ ./test.sh 2 7
>>> 1번째 인수가 2번째 인수보다 작다
>>> $ ./test.sh 10 5
>>> 1번째 인수가 2번째 인수보다 크다
>>> $ ./test.sh 9 9
>>> 1번째 인수와 2번째 인수가 동일하다
switch 조건
- switch의 기초 작성법은
case 변수 in 조건・값) 커맨드 ;; esac
임
- 조건・값이 변수와 일치하는 경우, 그 곳에 적힌 커맨드가 실행
#!/bin/sh
DRINK="coffee"
case "$DRINK" in
"beer") echo "맥주입니다"
;;
"juice") echo "주스입니다"
;;
"coffee") echo "프로그래머가 마시면 커피로 변화!"
;;
esac
>>> $ ./test.sh
>>> 프로그래머가 마시면 커피로 변화!
루프 (반복문)
- 루프(반복문)에서는
break
키워드로 종료할 수 있고
continue
키워드로 현재의 루프를 건너 뛸 수 있음
#!/bin/sh
a=0
while [ $a -lt 5 ]
do
echo $a
a=`expr $a + 1`
done
>>> $ ./test.sh
>>> 0
>>> 1
>>> 2
>>> 3
>>> 4
- until 루프
- while과 반대로 조건과 일치할 때까지 반복
#!/bin/sh
a=0
until [ ! $a -lt 5 ]
do
echo $a
a=`expr $a + 1`
done
>>> $ ./test.sh
>>> 0
>>> 1
>>> 2
>>> 3
>>> 4
- for 루프
- for의 기본 작성법은
for 변수 in 여러 개의 값・변수・범위 do 커맨드 done
임
- 조건과 값이 변수와 일치하는 경우 커맨드가 실행
#!/bin/sh
for var in 0 1 2 3 4
do
echo $var
done
>>> $ ./test.sh
>>> 0
>>> 1
>>> 2
>>> 3
>>> 4
함수
- 셸 스크립트에서는 함수를 작성하여 인용하는 것이 가능
#!/bin/sh
MyFunction () {
echo "함수의 echo이다."
}
MyParamFunc() {
echo "인수1:$1 인수2:$2"
}
MyFunction
MyParamFunc param1 param2
>>> $ ./test.sh
함수의 echo입니다.
인수1:param1 인수2:param2