bash 기초 문법을 배워보자 - Hello World! 부터 함수와 반복문까지
System/Shell Script

bash 기초 문법을 배워보자 - Hello World! 부터 함수와 반복문까지

 


  이번 게시글에서는 UNIX나 Linux에서 기본 쉘로 많이 사용되는[각주:1] bash 쉘에서 스크립트를 작성하는 방법에 대해 다루어 볼 것이다. 물론 bash 쉘 환경을 준비해 놓았다는 가정 아래에서이다. 참고로 글쓴이는 Kali Linux 2018.4-amd64 환경에서 vim 편집기로 실습을 했다.


Hello, World!


  프로그래밍 언어를 배우는 사람이라면 수도 없이 본 Hello, World!를 여기서도 한 번 출력해 보자.


1
2
#!/bin/bash
echo "Hello, World!"
cs


  파일 이름은 HelloWorld.sh[각주:2]로 저장하였다. 이때 유의해야 할 것은 방금 작성한 스크립트를 실행하려면 실행 권한을 부여해야 한다는 것이다. 아래와 같이 입력하여 실행할 수 있는 파일로 만들어주자.


1
chmod u+x HelloWorld.sh
cs


  실행하려면 커맨드 라인에 ./HelloWorld.sh라고 입력하면 된다. 명령어 앞에 있는 ./ 부분은 파일 시스템에 있는 HelloWorld.sh라는 명령어나 스크립트가 아닌 현재 디렉터리에 있는 HelloWorld.sh 스크립트를 실행하기 원한다는 의미이다.


  Hello World! 라고 출력되는 것을 확인했으면 다시 아까 작성했던 스크립트로 돌아가보자. 첫 번째 줄에 입력된 '#!/bin/bash' 는 '#!'와 '/bin/bash', 이렇게 두 부분으로 나눌 수 있다. '#!'는 셔뱅(shebang)이라고 하는 것으로, 운영체젱에게 어떤 인터프리터로 아래에 있는 스크립트를 인터프리트하고 싶다고 알려주는 것이다. '/bin/bash'는 사용하고 싶은 인터프리터이다. 다른 쉘 환경에서 인터프리트하고 싶다면 셔뱅 뒤에 오는 부분을 바꾸어 주면 된다. 파일 시스템 다른 곳에 bash가 설치되어 있을 가능성도 배제할 수는 없으므로, which나 bash 명령어로 bash의 위치를 미리 확인해두자. 두 번째 줄의 echo "Hello World!"는 단순히 Hello World!를 출력하는 명령문이다.[각주:3]


변수


  메모리에 어떤 값을 저장할 수 있게 하는 것이 변수인데, 크게 둘로 나눌 수 있다. 전역 변수(Global Variable), 그리고 지역 변수(Local Variable). 전역 변수는 쉘 전체에서 사용할 수 이쓴 변수로, 어떤 스크립트를 실행해도 볼 수 있다. 지역 변수는 현재 쉘에서만 존재하는 변수로 현재 쉘을 종료하면 사라져 버린다. 위에서 작성했던 HelloWorld.sh 스크립트를 조금 수정해서 변수에 대해 알아보자. (HelloWorld1.sh)

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
function localmessage
{
    local MESSAGE="Hi there! We're inside the function."
    echo $MESSAGE
}
MESSAGE="Hello, World! We're outside the function."
echo $MESSAGE
localmessage
echo $MESSAGE
cs

  HelloWorld1.sh 에서는 함수와 변수라는 두 가지 개념에 대해 알아볼 수 있다. 2행부터 6행까지는 localmessage라는 함수가 구현되어 있다. 함수는 반복해서 사용할 수 있는 특정 코드 부분을 따로 분리하여 몇 번이고 재사용할 수 있게 해 준다. 또한 함수 내에 선언된 변수를 함수의 지역 변수로 정의하여 전체 스크립트에서 따로 분리시킬 수도 있다.


  예시에 있는 함수 안에는 지역 변수[각주:4] MESSAGE가 하나 있고, "Hi there! We're inside the function." 이라는 메시지가 저장되어 있다. 5행에서 echo 명령어로 출력하는데, 변수라는 것을 알려주기 위해 변수 이름 앞에 '$'을 붙인다. 함수를 호출하기 위해서는 9행에서처럼 그냥 간단히 함수의 이름을 적어주면 된다.


  함수 밖에서도 MESSAGE 변수가 있는데, 7행의 MESSAGE는 4행의 MESSAGE와는 달리 전역 변수이다. 하나는 함수 안에서, 하나는 함수 밖에서 호출되는 것이다. 프로그램 실행 결과를 한 번 보자.


매개변수


  스크립트를 실행할 때 숫자나 문자열 같은 정보를 매개변수 형태로 스크립트에 전달할 수 있다. 예를 들어 두 수를 더해서 결과값을 출력하는 프로그램이라면 두 개의 숫자값을 전달할 필요가 있다.


1
2
3
#!/bin/bash
MESSAGE="Wake up, "$1"!"
echo $MESSAGE
cs

  다음과 같은 내용이 저장된 스크립트 variables.sh를 실행할 때에는 조금 다르게 해야 한다. 위에서 했던 대로라면 ./variables.sh 와 같이 해야 하겠지만, 그렇게 하면 "Wake up, !" 이라고밖에 안 나온다. 매개변수를 주지 않았기 때문이다.

  그러면 어떻게 해야 할까? 3행에서 MESSAGE 변수에 "Wake up, "이라는 문자열에 $1라는 값이 추가로 더 붙어있는 것을 볼 수 있다. 쉘에서 각각의 매개변수는 입력되는 순서대로 번호가 매겨진다. 따라서 $1은 첫 번째로 입력한 매개변수라는 뜻이다.[각주:5] 우리는 MESSAGE 라인에 $1을 입력함으로써 쉘이 "Wake up, ", "!" 텍스트 사이에 첫 번째 매개변수의 내용을 MESSAGE 변수에 저장하게 해야 한다.



※ 매개변수, 어디까지 쓸 수 있을까?

  대부분의 UNIX 계열 시스템에서는 getconf ARG_MAX 명령어로 사용할 수 있는 매개변수의 한계를 확인할 수 있다. 작성자의 가상환경에서는 2097152KB만큼 입력받을 수 있었다.


매개변수

의미

 $0

 스크립트 이름

 $1

 첫 번째 매개변수

 $2

 두 번째 매개변수

 $50

 50번째 매개변수

 $#

 가지고 있는 매개변수의 개수


  이 다음에는 제어문에 대해서 알아볼 것이다. 제어문은 스크립트가 실행되는 동안 그 흐름을 제어할 수 있게 해 주는 구문들이다. 간단히 조건문과 반복문에 대해서만 살펴보자.


조건문


  조건문은 입력값, 변수에 저장된 값, 또는 다른 요소에 따라 프로그램이 어떻게 작동할 지 선택해주는 역할을 한다. 조건문에도 여러 종류가 있지만, 역시 가장 흔히 사용되는 조건문은 if문이다. 아래의 if.sh 코드를 통해 if문을 사용하는 방법에 대해 알아보자.


1
2
3
4
5
6
7
#!/bin/bash
if [ "$1" = "Vallhalla" ]; then
    MESSAGE="Wake up, "$1"!"
else
    MESSAGE="Hey, you're not Vallhalla."
fi
echo $MESSAGE
cs


  첫 번째 매개변수를 어떻게 입력하느냐에 따라 출력되는 결과가 달라진다. 따라서 두 가지 결곽밧을 모두 보려면 스크립트 실행을 두 번 해야 한다.



  다시 코드로 돌아가 보자. 셔뱅 다음에 있는 if [ "$1" = "Vallhalla" ]; then 부분이 if.sh 스크립트의 핵심이다. 입력받은 첫 번째 매개변수의 값이 Vallhalla와 동일하다면 MESSAGE의 값을 "Wake up, "$1"!" 로 저장한다. 여기서 if문 첫 번째 행 앞에 있는 문자열과 $1의 값을 비교한다. 비교하여 나온 값이 거짓이면 4행으로 건너뛰어서 else 부분에 있는 코드를 실행한다. 이렇게 되면 MESSAGE는 "Hey, you're not Vallhalla." 가 된다. 마지막으로 fi는 if문이 끝났음을 표시하는 구문이다.


  값들을 비교하는 방법에는 여러 가지가 있는데, 문자열의 경우에는 문자를 하나만 추가하여 앞에서 예시로 보였던 if.sh의 구조를 완전히 뒤바꿀 수 있다. if문 첫 번째 라인에서 '='를 '!='으로 바꾸면 의미가 '같은'이 아니라, '같지 않은'으로 바뀐다. 한편 아래 표에 있는 수학 기호들을 사용하여 if문을 작성할 수도 있다.


연산자

의미

 -eq

 ~과 같다

 -ne

 ~과 같지 않다

 -gt

 ~보다 크다

 -lt

 ~보다 같다

 -le

 ~보다 작거나 같다


  표에 있는 값은 다음과 같이 응용할 수 있다. (comparenum.sh)


1
2
3
4
5
6
7
8
#!/bin/bash
NUM1 = $1
NUM2 = $2
if [ "$NUM1" -eq "$NUM2" ]; then
    echo "$NUM1 is equal to $NUM2."
else
    echo "$NUM2 is not equal to $NUM2."
fi
cs



  매개변수 두 개를 받아서 서로 같으면 if문을, 같지 않다면 else문 안 에 있는 명령어를 실행하는 스크립트이다.


반복문


  조건문과 마찬가지로 bash에서는 여러 방버으로 반복문을 실행할 수 있다. 대표적인 반복문으로는 for문과 while문이 있다. for와 while은 비슷한 결과를 가져오지만, 방식에서 차이를 볼 수 있다.

  for문을 사용하면 어떠한 목록에 있는 각각의 객체(아이템)에 대해 작업을 수행할 수 있다. 아래 예제 formedia.sh의 코드와 실행 결과를 한번 보도록 하자.

1
2
3
4
5
#!/bin/bash
for files in /media/*
do
    echo $files
done
cs


  파일 실행 결과와 ls /media 명령어의 출력 결과를 둘 다 나타내어 보았다. formedia.sh를 실행하였을 때 /media의 파일 및 디렉터리를 보여주는 것이 ls 명령어와 비슷한 것을 알 수 있다. 2행의 for files in /media/*에서 for문이 시작되었는데, 여기서 각 파일을 저장할 변수(예제에서는 files)를 설정하였다. 이어 /media/*를 사용하여 특정 디렉터리의 특정 내용을 읽게 하였다. 예제에서는 /media에 있는 모든 파일과 디렉터리(*)를 지정한 것이다. do와 done 구문이 반복문의 시작과 끝을 표시하고, 그 사이에 앞에서 정의 한 files 변수를 출력하게 했다. 이 스크립트를 조금 변경하면 전 파일 시스템에서 어떠한 파일을 찾게 해서 그 파일을 복사하는 등 다양한 작업을 하게 할 수도 있다.


  이번에는 while 문을 사용해 보자. while문은 조건이 참인 동안 계속해서 반복적으로 실행한다. 즉, 조건만 된다면 무한히 반복한다는 것이다. 그 예제인 while.sh 스크립트를 살펴보자.


1
2
3
4
5
6
7
#!/bin/bash
i=0
while [ $1 -lt 5 ]
do
    echo "Strawberry Milk"
    i=$[$i+1]
done
cs


  2행의 i=0에서는 반복문 안에서 사용할 변수를 설정하였다. 여기서 변수 i는 반복 횟수를 지정하는 일종의 카운터 역할을 한다. 3행에 대괄호 안에 있는 구문은 i의 값이 5보다 작으면 do ~ done 사이에 있는 구문을 계속해서 실행한다는 뜻이다. 6행에서는 i값을 1만큼 더 올려준다. while.sh를 실행한 결과는 아래와 같다.




  1. 간혹 Windows에서도 배시가 설치되어 있을 수도 있다. [본문으로]
  2. sh는 스크립트 파일의 확장자이다. [본문으로]
  3. echo는 bash 명령어 중 하나로, 명령어 뒤에 인자로 오는 문자열이나 숫자 등을 콘솔 창 위에 출력한다. [본문으로]
  4. local 키워드로 알 수 있다. [본문으로]
  5. $0은 스크립트를 실행시킬 때 프로그램의 이름이 포함된 첫 번째 문자열이 저장된다. [본문으로]