2023.04.02

bash 문법

퇴사 이후… 장비를 포맷하면서 기존에 사용하던 vscode extension이나 환경들을 다시 설치해야한다는 문제점이 있다. 이번에 개인 로컬 환경을 설정해서 설치해주는 쉘 스크립트를 구성하면서 사부작 bash 쉘 문법도 정리 해본다..


스크립트의 시작…!

스크립트의 시작은 #!/bin/bash 로 시작한다.

어..? # 로 시작하면 주석이라 실행되지 않는게 맞지 않나?

물론 #으로 시작하면 주석이 맞지만, ! 가 붙는 경우 프로그램 로더가 다음 줄 부터는 인터프리터 구문으로 분석을 하게 됩니다. #! 이후에 붙는 경로는 해당 쉘의 명령어 집합(?)들이 있는 경로이다. 이전 글에서 쉘에는 여러 종류가 있고 인터프리터로 실행된다는 이야기 한 적이 있다. 시작에 어떤 쉘을 사용할 건지 정의를 해주어야 한줄 한줄 읽을 때 해당 쉘에 맞는 커맨드로 실행되게 된다. 그렇기에 스크립트는 첫줄에 항상 정의해주는 것이 좋다.


다른 쉘의 경우, #!/bin/sh 등 해당 쉘에 맞게 작성해두면 된다.


변수 선언

bash 에서 변수로는 다른 언어처럼 지역변수, 전역변수, 환경변수, 예약변수, 매개변수 등이 있다. 우선 범위가 넓은 순서대로 확인해보자.


예약변수

시스템에서 미리 정의가 된 변수이다. 해당 변수와 같은 이름의 변수로 처리하는 경우 오류가 남발할 수 있기 때문에 예약변수의 이름과 동일하게 작성되지 않도록 주의해야한다.


환경변수

현재 환경에서 공통적으로 사용될 변수를 의미한다.

주로 우리 컴퓨터는 OS를 설치해두는데, 해당 OS 내부에서 공통적으로 쓰이는 변수라고 이해하면 될 것 같다. 이는 단순히 OS 만이 아니라 OS 하위 프로세스까지 변수가 전달된다는 점만 인지하면 될 것 같다. export로 지정을 한다.

export AWS_ACCESS_KEY='aws 접속 키'


매개변수

매개변수는 함수에 전달하는 변수가 아니라 스크립트로 전달하는 값을 의미한다. 따라서 해당 매개변수를 순서에 따라 구분을 하게 되는데… 자세한 것은 아래와 같다. 이는 스크립트에 한정되지 않고 함수에도 적용된다.

sh test_scripts.sh test 100
코드 의미
$0 쉘 스크립트 이름(ex: test_scripts.sh)
$1 첫번째 매개변수 (ex: test)
$2 첫번째 매개변수 (ex: 100)
 
$* 전체 매개변수 (ex: test 100)
$@ 전체 매개변수 (ex: test 100)
$# 전체 매개변수 개수 (ex: 2)
$$ 스크립트 프로세스 아이디 (ex: 2823)
$! 이전에 실행된 프로세스 아이디
$? 마지막으로 실행된 종료 코드 (ex: 0)

Screenshot 2023-04-01 at 4 31 07 PM


전역변수

전역변수는 쉘에서 선언된 변수들을 의미한다. 여기서 쉘은 스크립트를 의미하고, 현재 실행되는 스크립트 내부에서만 전역적으로 작용한다. 만약 해당 스크립트에서 A 스크립트를 호출하는 경우에 A 스크립트에서는 해당 변수 값을 사용하지 못하기 때문에 별도로 전달을 해주어야 한다.


지역변수

지역변수는 스크립트에서… 특정 함수(지역)에서만 사용이 가능한 변수를 의미한다. 주로 local 을 변수 앞에 붙여두는 형식으로 해당 함수 외부에서는 사용할 수 없다. 만약 local 을 붙이지 않는 경우 전역변수로 인식하기 때문에 이 경우에는 외부에서 사용할 수 있다.


변수 출력은 어떻게…?

전역변수와 지역변수의 경우 스크립트 내부에 작성하는 경우 echo $변수명 를 이용해서 출력할 수 있다.

#!/bin/bash
banana='바나나'
echo $banana # 바나나 출력


전역과 지역 변수의 변수명이 같은 경우…?

아무리 전역이라도 지역변수는 그 지역 짱이기 때문에 아래와 같이 출력된다. 이런 점은 환경변수 와 전역, 지역 변수에서도 적용이 된다. 즉, 환경변수에서 어떤 값을 지정해두어도 스크립트 내부에서는 다르게 지정할 수 있다는 점이다.

#!/bin/bash

result='apple'

print_result() {
	local result='banana'
	echo $result
}

print_result # banana 출력
echo $result # apple 출력


지역과 전역의 메모리

추가적으로 전역, 지역변수의 메모리 구조도 다르다. 지역변수의 경우 스택에 저장이 되고, 전역변수의 경우 고정된 메모리에 저장되기 때문에 정말로 특정 공간에서만 사용되는 경우 지역변수를 할당하는 것이 좋을 것이다. 전역변수는 스크립트가 끝나면 메모리를 해제하게 되고, 지역변수의 경우 해당 함수가 끝나면 해제된다….

그 외에 초기 값 또한 지역변수의 경우 가비지… 전역은 0으로 설정된다.


함수 선언

전역과 지역 변수의 변수명이 같은 경우…? 에서 예시 코드와 같이 함수를 정의 할 수 있다. 함수의 경우 마지막 커맨드의 종료 코드값을 전달하기에 이점을 유의 하자. 그렇기 때문에 함수 내부에서 return을 사용할 수는 있지만, 그 값은 0~255 내의 정수여야 한다. 0인 경우 정상 종료이다.

print_dog() {
	echo 'dog'
}

print_dog # dog 출력

또는… 아래처럼 작성할 수 도 있다.

function print_dog {
	echo 'dog'
}


함수에 전달된 값은 매개변수와 같이 사용하면 된다.

#!/bin/bash

print_dog() {
	echo 'first: '$1
	echo 'second: '$2
}

print_dog '리트리버' '불독'

함수 내부에서 특정 이름으로 사용하고 싶은 경우 지역변수, 전역변수로 따로 작성해서 사용해야한다.

#!/bin/bash

print_dog() {
  local first_dog=$1
  local second_dog=$2
	echo 'first: '$first_dog
	echo 'second: '$second_dog
}

print_dog '리트리버' '불독'



Categories:

Updated:

Leave a comment