[Shell Script] 간단한 쉘 스크립트 문법 정리와 예제
업데이트(2020.12.26): 변수 관련 parameter expansion과 따옴표 관련 내용 추가
업데이트(2019.09.08): 배열과 조건문에 예제들 추가
쉘 스크립트 사용법을 간단하게 정리하고 예제를 사용해보자
환경
- Linux 기반 시스템
- Bash shell(/bin/bash)
쉘 스크립트 작성 및 권한 부여
파일생성 및 권한 부여
- 파일생성
$ touch shell_script_practice.sh // 파일 생성
$ vim shell_script_practice.sh // 쉘 스크립트 파일 편집기로 열기
- 실행 권한 부여(파일의 상태 변경)
$ chmod +x shell_script_practice.sh // 실행 권한 부여
스크립트 상단에 #!/bin/bash 추가
#!/bin/bash
... 하단에 스크립트 작성 ...
쉘 스크립트 실행 방법
./[쉘스크립트 파일명]
$ ./shell_script_practice.sh
기본 문법과 예제
기본 출력
echo
,printf
echo "Echo Test" # 자동 개행
printf "printf Test" # 자동 개행X
printf "%s %s" print test # 뒤에 오는 문자열들이 전달되는 인자라고 생각하면 됩니다.
$#
: 스크립트에 전달되는 인자들의 수(C언어에서 argc)$0
: 실행하는 스크립트의 파일명으로 실행했을 때 경로를 포함한다면 경로를 포함해서 나옵니다.$1
,$2
…: 스크립트로 전달된 인자들(C언어에서 argv[0], argv[1]…)
#!/bin/bash
echo "Echo Test"
printf "printf Test\n"
printf "Name of script: %s\n" $0
printf "%d arguments %s %s\n" $# $1 $2
주석
#
를 사용
# echo "Echo Test"
변수 선언
=
를 이용해서 선언하고$
를 이용해서 사용=
는 공백 없이 붙여써야한다.- 지역변수에는
local
을 붙인다. {}
는parameter expansion
으로$
와 함께 감싼 부분에 변수를 대입해준다.(https://superuser.com/questions/935374/difference-between-and-in-shell-script) 여러 표현 방법을 통해 다양하게 사용이 가능하다.- 변수가 선언되지 않았을때
default_value=${default_value:="example default value"}
처럼 기본값을 사용하도록 설정 가능하다. ""
로 감싸서 사용하면 더 안전하다. 문자열에 공백도 포함해서 값을 이용할 수 있기 때문이다.Ex) $ex -> "${ex}"
#!/bin/bash
# shell script variable
test="abc"
num=100
# variable usage
echo ${test}
echo ${num}
echo "${test}"
echo "${num}"
# local variable
local local_val="local one"
# If variable default_value is not set, set it to "example default value" and assign again.
default_value=${default_value:="example default value"}
- 만약
{}
(parameter expansion
)을 사용하지 않으면 아래와 같은 경우에 변수test
가 아닌 변수test5678
을 불러오게 된다.
test=1234
echo "This is $test5678" # "This is "
echo "This is ${test}5678" # "This is 12345678"
- 만약
""
로 감싸지 않으면 아래와 같은 조건문에서unary operator expected
라는 오류가 생길 수 있다. - 치환을 하는 형태이기 때문에 아래의 식이
if [ == " " ]
로 바뀌기 때문이다.
blank=" "
if [ ${blank} == " " ]
then
echo "blank test"
fi
배열
기본
- 아래처럼
배열이름=(원소1 원소2 ...)
의 형태로 선언 - 배열의 인덱스는
0
부터 시작합니다. 배열이름[@]
는 배열의 모든 원소를 의미합니다.
#!/bin/bash
arr_test_string=("abc" "def" "ghi" "jkl")
echo "${arr_test_string[2]}"
arr_test_char=('a' 'b' 'b')
echo "${arr_test_char[0]}"
arr_test_num=(1 2 3 100 10000)
echo "${arr_test_num[3]}"
echo "${arr_test_num[@]}"
배열에 원소 추가
+=
연산자를 사용
#!/bin/bash
arr_test_string=("abc" "def" "ghi" "jkl")
arr_test_string+=("mno")
arr_test_string+=("pqr" "stu")
for i in ${arr_test_string[@]}; do
echo $i
done
arr_test_string=(1 2 3 4 5)
arr_test_string+=(6)
arr_test_string+=(7 8)
for i in ${arr_test_string[@]}; do
echo $i
done
배열에서 원소 삭제
/
를 사용해 해당 문자열 부분이 있으면 삭제, 삭제하고자 하는 문자나 문자열이 포함되어있는 부분을 모두 삭제합니다.- (권고)
unset
을 이용해 삭제
#!/bin/bash
arr_test=(1 2 3)
remove_element=(3)
arr_test=( "${arr_test[@]/$remove_element}" )
for i in ${arr_test[@]}; do
echo $i
done
arr_test=("abc" "def" "ghi")
remove_element=("ghi")
arr_test=( "${arr_test[@]/$remove_element}" )
for i in ${arr_test[@]}; do
echo $i
done
# !!! Be careful when you delete like below !!!
# Use second method in this case
arr_test=("abc" "def" "defghi")
remove_element=("def")
arr_test=( "${arr_test[@]/$remove_element}" )
for i in ${arr_test[@]}; do
echo $i
done
#!/bin/bash
arr_test=("abc" "def" "defghi")
remove_element=("def")
# Get index of array
echo ${!arr_test[@]}
for i in ${!arr_test[@]}; do
if [ ${arr_test[i]} = ${remove_element} ]; then
# Use unset
unset arr_test[i]
fi
done
for i in ${arr_test[@]}; do
echo $i
done
조건문
if [ 조건 ]; then ... elif [ 조건 ]; then ... else
를 사용합니다.if (( 산술 연산 )); then ... elif (( 산술 연산 )); then ... else
- 연산자 관련된 부분은 https://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/comparison-ops.html를 참조
#!/bin/bash
# Numeric if statement
test_num=5
if [ "${test_num}" -eq 2 ]; then
echo "number is 2"
elif [ "${test_num}" -eq 3 ]; then
echo "number is 3"
else
echo "number is not 2 or 3"
fi
# Numeric if statement
test_num=5
if (( ${test_num} > 3 )); then
echo "number is greater than 3"
else
echo "number is not greater than 3"
fi
# String if statement
test_str="test"
if [ "${test_str}" = "test" ]; then
echo "test_str is test"
else
echo "test_str is not test"
fi
반복문
while
문의 사용
#!/bin/bash
cnt=0
while (( "${cnt}" < 5 )); do
echo "${cnt}"
(( cnt = "${cnt}" + 1 )) # 숫자와 변수의 연산은 (())가 필요합니다.
done
for
문의 사용법
#!/bin/bash
arr_num=(1 2 3 4 5 6 7)
# 배열에 @는 모든 원소를 뜻합니다.
for i in ${arr_num[@]}; do
printf $i
done
echo
for (( i = 0; i < 10; i++)); do
printf $i
done
echo
참고자료
- https://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/comparison-ops.html
- https://ko.wikipedia.org/wiki/셸_스크립트
- https://blog.gaerae.com/2015/01/bash-hello-world.html
- http://w51014.tistory.com/1
- https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
- https://tldp.org/LDP/abs/html/parameter-substitution.html