$변수명
: 변수 사용
readonly 변수명
: 읽기전용 변수로 선언 (읽기 전용 변수 값을 바꾸려고 시도하면 에러 발생)
unset 변수명
: 변수 할당 해제
Script 내에서 선언한 변수 뿐만 아니라, 환경 변수, 쉘 변수(접속한 shell에서 export로 선언한 변수)도 $변수 로 읽어올 수 있다.
내가 변수로 할당하지 않았는데 특수한 문자들로 쓸 수 있는 변수들을 의미한다.
$
: 현재 Shell 의 프로세스 아이디$0
: 현재 script 의 파일 이름(0번째 인자, 자기 자신)$n
: script 실행시 넘겨준 n번째 인자$#
: script 에 넣어준 인자의 개수$*
: 모든 인자를 ""로 감싸서 반환$@
: 각 인자를 "" 로 감싸서 반환$?
: 마지막으로 실행된 명령어의 종료 상태$!
: 마지막 백그라운드 명령어의 프로세스 아이디$*
vs $@
차이 실습$@
와 $*
의 차이를 구분해서 사용해야한다. 이 둘의 차이는 스크립트가 또 다른 명령어를 불러올 때 드러난다.
arg-callee.sh
, arg-caller.sh
예제로 인자가 어떻게 전달되는지 살펴보자.
arg-callee.sh
#!/bin/sh
echo "arg 1: $1"
echo "arg 2: $2"
echo "arg 3: $3"
echo
arg-caller.sh
#!/bin/sh
echo '$* without quotes:'
./arg-callee.sh $*
echo '$@ without quotes:'
./arg-callee.sh $@
echo '$* with quotes:'
./arg-callee.sh "$*"
echo '$@ with quotes:'
./arg-callee.sh "$@"
arg-caller.sh에 실행 권한을 부여하고
arg-caller.sh에 apple
banana
"cherry pie"
전달
chmod +x arg-caller.sh arg-callee.sh # 실행 권한 부여 ./arg-caller.sh apple banana "cherry pie"
$*
실행 결과:
arg 1: apple
arg 2: banana
arg 3: cherry
$*
은 전달된 인자들을 "하나의 문자열로 합쳐서" 반환$@
실행 결과:
arg 1: apple
arg 2: banana
arg 3: cherry
$*
과 동일하게 "cherry pie"가 "cherry"와 "pie"로 나뉘어 전달됨$@
는 전달된 인자들을 각각의 인자로 유지"$*"
실행 결과:
arg 1: apple banana cherry pie
arg 2:
arg 3:
$*
을 따옴표
로 감싸면 모든 인자가 하나의 문자열로 합쳐져서 전달됨"$@"
실행 결과:
arg 1: apple
arg 2: banana
arg 3: cherry pie
$@
을 따옴표
로 감싸면 각 인자가 원래 형태 그대로 유지$?
(Exit Status) 실습$?
: 마지막으로 실행된 명령어의 상태를 확인
exit 0
: 정상종료, 성공
0이 아닌다른 숫자값
: 기본적으로 실패를 나타냄
fail.sh
#!/bin/sh
echo "fail"
exit 1
success.sh
#!/bin/sh
echo "success"
exit 0
process-call.sh
#!/bin/sh
./fail.sh # 또는 ./success.sh
if [ $? -ne 0 ]; then
echo "failed from sub command"
exit 1
fi
echo "next step"
process-call.sh
실행 결과
process-call.sh
안에서 적어놓은 ./fail.sh
또는 ./success.sh
실행한다$!
실습$!
: 마지막으로 실행된 백그라운드 프로세스의 PID(Process ID)를 반환
process-call.sh
#!/bin/sh
./success.sh
if [ $? -ne 0 ]; then
echo "failed from sub command"
exit 1
fi
sleep 100 & # 백그라운드에서 실행
echo "background sleep pid: $!"
echo "next step"
./process-call.sh
실행 결과
출력
success
background sleep pid: 13927
next step
success
: ./success.sh 실행 결과background sleep pid: 13927
: sleep 100 &
가 백그라운드에서 실행됨 next step
: 스크립트 정상 종료백그라운드 프로세스 확인
ps -ef | grep 13927
출력
501 13927 1 0 2:57PM ttys000 0:00.00 sleep 100
501 13966 10215 0 2:58PM ttys000 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox --exclude-dir=.venv --exclude-dir=venv 13927
백그라운드 프로세스 종료
kill -9 13927
$!
은 마지막으로 실행된 백그라운드 프로세스의 PID를 저장하는데
sleep 100 &
을 실행 후 $!
기능으로 해당 프로세스의 PID를 확인해 보았다.
if
는 항상fi
로 닫는다.;
then
으로 다음 수행을 알려준다.If [ condition ]; then
${if script}
elif [ condition ]; then
${elif script}
else
${else script}
fi
case
는 항상 esac
로 닫는다.in
과 pattern
이 와야한다.*)
는 default, 위의 어떤 조건도 아닐 때 수행한다.case word in
pattern 1)
Statement(s) to be executed if pattern1 matches
;;
pattern 2)
Statement(s) to be executed if pattern2 matches
;;
*)
Default condition to be executed
;;
esac
case.sh
#!/bin/sh
OPTION="${1}" # 첫 번째 입력 인수를 OPTION 변수에 저장
case ${OPTION} in
-f) FILE="${2}"
echo "FILE Name is $FILE"
;;
-d) DIR="${2}"
echo "Dir name is $DIR"
;;
[0-9]) NUM="${1}"
echo "number is $NUM"
;;
*)
echo "`basename ${0}`: usage: [-f file] | [-d directory]"
exit 1
;;
esac
위에서 case로 만든 패턴, 파일 옵션(-f)을 사용
./case.sh -f test.txt
출력
FILE Name is test.txt
-f
옵션을 입력했으므로 FILE="${2}" 실행패턴 형식의 Regular Excpression도 사용 가능하다.
Bourne shell
(기본연산자) 에는 arithmetic operations
(더하기/빼기같은 대수 연산 operator) 이 없기 때문에 외부 프로그램인 awk
또는 expr
를 사용해야 한다.
2+2
로 쓰면 "2+2"
문자열이 그대로 출력됨)*
연산은 앞에 \
입력 해줘야 함곱하기 예제
expr 4 \* 2
expr 4 * 2 로 입력했을 경우 출력 :
expr: syntax error
+
: 더하기 expr $a + $b
로 사용한다-
: 빼기 expr $a - $b
로 사용한다*
: 곱하기 expr $a \* $b
로 사용한다/
: 나누기 expr $a / $b
로 사용한다%
: 나머지 연산자 expr $a % $b
로 사용한다=
: 값 할당 a=$b 로 사용하면 b의 값이 a에 할당된다[ $a=$b ]
: 값이 같은 경우에 true, 값 비교[ $a!=$b ]
: 값이 다른경우에 true (이때 반드시 [ ] 대괄호와 값 사이에 space 가 있어야함.)-eq
: 두 값이 같은 경우 true-ne
: 두 값이 다른 경우 true-gt
: 왼쪽 값이 오른쪽 값보다 큰 경우 true 반환-lt
: 왼쪽 값이 오른쪽 값보다 작은 경우 true 반환-ge
: 왼쪽 값이 오른쪽 값보다 크거나 같은 경우 true 반환-le
: 왼쪽 값이 오른쪽 값보다 작거나 같은 경우 true 반환실습
relation.sh
#!/bin/sh
if [ $1 -eq $2 ]; then
echo "$1 is equal to $2"
fi
if [ $1 -ne $2 ]; then
echo "$1 is not equal to $2"
fi
if [ $1 -gt $2 ]; then
echo "$1 is greater than $2"
fi
if [ $1 -lt $2 ]; then
echo "$1 is less than $2"
fi
if [ $1 -ge $2 ]; then
echo "$1 is greater than or equal to $2"
fi
if [ $1 -le $2 ]; then
echo "$1 is less than or equal to $2"
fi
./relation.sh 3 5
결과
3 is not equal to 5
3 is less than 5
3 is less than or equal to 5
./relation.sh 4 4
결과
4 is equal to 4
4 is greater than or equal to 4
4 is less than or equal to 4
./relation.sh 6 2
결과
6 is not equal to 2
6 is greater than 2
6 is greater than or equal to 2
!
: 논리적인 부정
-o
: OR 연산자
-a
: AND 연산자
실습 스크립트
bool.sh
#!/bin/sh
if [ !false ]; then
echo "not false is true"
fi
if [ $1 -gt $2 -o $1 -eq $2 ]; then
echo "$1 is greter than or equal to $2"
fi
if [ $1 -gt $2 -a $1 -lt $2 ]; then
echo "never happend"
fi
./bool.sh 1 1
실행결과
not false is true
1 is greater than or equal to 1
./bool.sh 1 2
실행결과
not false is true
어느 경우에도 마지막 세번째 조건에는 해당이 안되는 것을 볼 수 있다.
while / do / done 을 이용해 반복문을 선언할 수 있다.
while.sh
(반복문 예제)
#!/bin/sh
a=0
while [ $a -lt 10 ]
do
echo "$a"
a=$(expr $a + 1)
done
''
을 이용하면 위의 특수 목적 문자를 출력할 수 있다.''
를 사용해야 하는경우 ""
를 이용하여 ''을 출력할 수 있다.``
를 이용하여 ``내부의 shell 명령어를 실행할 수 있다.연습 예제
echo <-$1500.**>; (update?)[y|n] 을 표현하는 방법으로 아래 두가지를 사용할 수 있다.
test1
스크립트
echo '<-$1500.**>; (update?) [y|n]'
결과
<-$1500.**>; (update?) [y|n]
test2
스크립트
echo "<-$1500.**>; (update?) [y|n]"
결과
<-.**>; (update?) [y|n]
test3
스크립트
echo "<-$1500.**>; (update?!) [y|n]"
결과
zsh: event not found: )
test4
스크립트
echo "<-\$1500.**>; (update?\!) [y|n]"
결과
<-$1500.**>; (update?!) [y|n]
test5
스크립트
echo "`expr 2 + 2` is 2 + 2"
결과
4 is 2 + 2
echo -e
: backslash escape 을 적용할 수 있다\\
: backslash\a
: alert\n
: 줄 바꿈\b
: backspace\r
: 캐리지 리턴 (맨 앞으로 이동)\c
: 줄바꿈 삭제\t
: 가로 방향으로 tab 만큼 띄움\f
: form 양식\v
: 세로 방향으로 tab 만큼 띄움form 양식 실습
form 양식
은 한 칸을 띄우면서 마지막 줄로 들여쓰기를 한 다음에 입력
스크립트
echo -e "first\fsecond\fthird"
결과
first
second
third
실습 2
\v
도 form 양식과 같이 개행하면서 탭을 띄움
스크립트
echo -e "first\vsecond\vthird"
결과
first
second
third
캐리지리턴
: 백슬래시 R 만나면 맨 앞으로 간 다음에 거기서부터 내가 입력한 걸로 바꿔줘. 라는 것.
스크립트
echo -e "This is my friend\rwhere"
결과
whereis my friend
우리가 자주 사용하는 것들을 기능으로 만들고 그 다음부터는 그 기능을 함수 이름으로 호출해서 반복 재사용하고싶을 때 사용.
shell 스크립트같은 경우 위에서 아래로 쭉 읽기 때문에 함수가 위에서 정의가 되어 있어야 밑에서 사용 할 수 있다.
function_name (){}
: 함수 선언function_name
: 함수 사용function_name param1 param2
: 함수에 파라미터 param1 param2 전달Hello (){
echo "Hello World $1"
return 10
}
Hello FastCampus
실습 : function.sh
#!/bin/sh
myfunc(){
echo $1
echo $2
echo `expr $1 + $2`
}
myfunc 2 4
echo "$1 $2 are shell param"
./function.sh 1 3
출력
2
4
6
1 3 are shell param
스크립트에 넘겨준 파라미터 1,3 은 똑같이 $1, $2 라고 되어 있지만
함수 안에 것과 shell 스크립트 자체에 있는 것은 다른 것을 확인할 수 있다.