[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


조건문

#!/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


참고자료