Bash에서 변수로 작업하는 방법

스크립트를 작성하고 웹에서 복사 붙여넣기 한 코드가 리눅스 컴퓨터에 어떤 영향을 미치는지 파악하려면 변수에 대한 이해가 필수적입니다. 이제 시작해 보겠습니다!

변수 기초

변수는 문자열 또는 숫자 값을 나타내는 명명된 기호입니다. 명령어나 표현식에서 사용될 때, 변수 이름은 그 안에 저장된 값으로 대체됩니다. 이는 변수 이름을 직접 입력한 것과 같은 효과를 냅니다.

변수를 생성하려면 이름과 값을 지정하기만 하면 됩니다. 변수 이름은 변수의 역할을 명확히 설명해야 하며, 그 안에 어떤 값이 저장되는지 쉽게 알 수 있도록 해야 합니다. 변수 이름은 숫자로 시작하거나 공백을 포함할 수 없지만 밑줄로 시작하는 것은 허용됩니다. 그 외에, 대문자와 소문자 영숫자를 혼합하여 사용할 수 있습니다.

변수 예시

이제 5개의 변수를 만들어 보겠습니다. 변수를 정의하는 형식은 ‘변수 이름 = 값’ 입니다. 등호 앞이나 뒤에는 공백이 없어야 합니다. 변수에 값을 할당하는 것을 종종 변수에 값을 ‘지정한다’고 표현합니다.

아래에는 4개의 문자열 변수와 1개의 숫자 변수 ‘this_year’를 만들었습니다.

me=Dave
my_boost=Linux
him=Popeye
his_boost=Spinach
this_year=2023

변수에 저장된 값을 확인하려면 echo 명령어를 사용하세요. 변수에 저장된 값을 참조할 때는 변수 이름 앞에 달러 기호($)를 붙여야 합니다.

echo $me
echo $my_boost
echo $this_year

이제 모든 변수를 한 번에 사용해 보겠습니다.

echo "$my_boost is to $me as $his_boost is to $him (c) $this_year"

변수 값은 변경이 가능합니다. 변수 ‘my_boost’에 새 값을 할당하려면 처음 값을 할당했을 때와 같은 방식으로 하면 됩니다.

my_boost=Tequila

이제 이전 명령을 다시 실행하면 다른 결과가 나타납니다.

echo "$my_boost is to $me as $his_boost is to $him (c) $this_year"

이처럼, 동일한 명령어를 사용하더라도 변수에 저장된 값이 변경되면 다른 결과를 얻을 수 있습니다.

변수 인용에 대해서는 나중에 자세히 다루겠습니다. 지금은 다음 사항들을 기억해 두세요.

  • 작은 따옴표(‘) 안에 있는 변수는 변수가 아닌 문자 그대로의 문자열로 취급됩니다.
  • 큰 따옴표(“)로 묶인 변수는 변수로 취급됩니다.
  • 변수에 저장된 값을 얻으려면 달러 기호($)를 사용해야 합니다.
  • 달러 기호($) 없이 변수를 사용하면 변수 이름 자체를 의미합니다.

기존 변수 또는 여러 변수의 값을 조합하여 새로운 변수를 만들 수도 있습니다. 아래 명령어는 ‘drink_of_the_Year’라는 새로운 변수를 정의하고 ‘my_boost’ 및 ‘this_year’ 변수를 결합한 값을 할당합니다.

drink_of_the_Year="$my_boost $this_year"
echo $drink_of_the_Year

스크립트에서 변수 사용

변수 없이 스크립트는 제대로 작동하기 어렵습니다. 변수를 사용하면 스크립트를 특정 상황에 국한되지 않고 일반적인 문제 해결 도구로 만들 수 있습니다. 차이점을 설명하기 위해 ‘/dev’ 디렉토리에 있는 파일 수를 계산하는 스크립트를 예로 들어 보겠습니다.

아래 코드를 텍스트 파일에 입력하고 ‘fcnt.sh'(‘파일 수’의 약자)로 저장하세요.

#!/bin/bash
  folder_to_count=/dev
  file_count=$(ls $folder_to_count | wc -l)
  echo $file_count files in $folder_to_count

스크립트를 실행하기 전에 아래와 같이 실행 가능하도록 만들어야 합니다.

chmod +x fcnt.sh

이제 다음 명령어를 입력하여 스크립트를 실행해 보세요.

./fcnt.sh

스크립트는 ‘/dev’ 디렉토리에 있는 파일 수를 출력합니다. 작동 방식은 다음과 같습니다.

  • ‘folder_to_count’라는 변수가 정의되었고, 그 값은 “/dev” 문자열로 설정되어 있습니다.
  • ‘file_count’라는 또 다른 변수가 정의됩니다. 이 변수는 명령어 대체를 통해 값을 얻습니다. 명령어 대체는 $( ) 괄호 안에 명령어를 입력하는 방식으로 사용하며, 괄호 앞에 달러 기호($)를 붙여야 합니다. 이 구조 $( )는 괄호 안의 명령어를 실행하고 결과 값을 반환합니다. 반환된 값은 ‘file_count’ 변수에 할당됩니다. ‘file_count’ 변수 입장에서는 어떤 방식으로 값이 주어졌는지는 중요하지 않습니다.
  • 명령어 대체에서 실행되는 명령어는 ‘folder_to_count’ 변수에 저장된 디렉토리(“/dev”)에 대해 파일 목록을 출력하는 ‘ls’ 명령어입니다. 따라서 스크립트는 ‘ls /dev’ 명령어를 실행합니다.
  • 이 명령어의 출력은 ‘wc’ 명령어로 파이프됩니다. ‘wc’ 명령어의 ‘-l'(줄 수) 옵션은 ‘ls’ 명령어의 출력에서 줄 수를 세도록 합니다. 각 파일은 별도의 줄에 나열되므로 ‘/dev’ 디렉토리에 있는 파일 및 하위 디렉토리의 수가 됩니다. 이 값이 ‘file_count’ 변수에 저장됩니다.
  • 마지막 줄은 결과를 출력하기 위해 ‘echo’ 명령어를 사용합니다.

하지만 이 스크립트는 ‘/dev’ 디렉토리에서만 작동합니다. 모든 디렉토리에서 작동하도록 하려면 어떻게 해야 할까요? 아주 작은 변화 하나만 있으면 됩니다.

스크립트에서 명령줄 매개변수 사용

‘ls’ 및 ‘wc’와 같은 많은 명령어들은 명령줄 매개변수를 사용합니다. 명령줄 매개변수는 명령어에 정보를 제공하여 명령어가 수행해야 할 작업을 알려줍니다. ‘ls’ 명령어를 홈 디렉토리에서 실행하고 숨김 파일까지 표시하려면, 물결표(~)와 ‘-a'(all) 옵션을 사용하여 다음과 같이 명령어를 사용할 수 있습니다. 여기서 물결표(~)와 -a 옵션이 명령줄 매개변수가 됩니다.

ls ~ -a

스크립트도 명령줄 매개변수를 받아들일 수 있습니다. 첫 번째 매개변수는 ‘$1’, 두 번째 매개변수는 ‘$2’, 최대 아홉 번째 매개변수는 ‘$9’로 참조합니다. 사실 ‘$0’도 있지만, 이 값은 항상 스크립트 이름을 저장하는 데 사용되도록 예약되어 있습니다.

일반 변수와 마찬가지로 스크립트에서 명령줄 매개변수를 참조할 수 있습니다. 스크립트를 아래와 같이 수정하고 새 이름 ‘fcnt2.sh’로 저장해 보세요.

#!/bin/bash
  folder_to_count=$1
  file_count=$(ls $folder_to_count | wc -l)
  echo $file_count files in $folder_to_count

이번에는 ‘folder_to_count’ 변수에 첫 번째 명령줄 매개변수인 ‘$1’의 값이 할당됩니다.

나머지 스크립트는 이전과 동일하게 작동합니다. 이 스크립트는 특정 디렉토리에서만 작동하는 것이 아닌, 일반적인 솔루션이 되었습니다. 이제 ‘/dev’ 디렉토리와 같이 특정 디렉토리에 국한되지 않고 모든 디렉토리에서 사용할 수 있습니다.

스크립트를 실행 가능하게 만드는 명령어는 다음과 같습니다.

chmod +x fcnt2.sh

이제 여러 디렉토리를 시도해 봅시다. 먼저 ‘/dev’ 디렉토리를 시도하여 이전과 동일한 결과를 얻을 수 있는지 확인해 보세요. 다음 명령어를 입력합니다.

./fcnt2.sh /dev
./fcnt2.sh /etc
./fcnt2.sh /bin

‘/dev’ 디렉토리에 대해 이전과 동일한 결과(파일 수)를 얻었습니다. 다른 디렉토리에 대해서도 각각 파일 수를 얻을 수 있습니다.

스크립트를 더 간결하게 만들려면 다음과 같이 ‘folder_to_count’ 변수를 생략하고 전체에서 ‘$1’만 참조하도록 변경할 수 있습니다.

#!/bin/bash
  file_count=$(ls $1 | wc -l)
  echo $file_count files in $1

특수 변수 사용

스크립트 파일 이름으로 설정되는 ‘$0’에 대해 언급했습니다. 이렇게 하면 스크립트 이름을 변경하더라도 스크립트가 자신의 이름을 올바르게 출력하는 등의 작업을 할 수 있습니다. 이는 로그를 기록할 때 스크립트 이름을 함께 기록하는 데 유용합니다.

다음은 그 외 다른 특수 변수들입니다.

  • $# : 스크립트에 전달된 명령줄 매개변수의 수
  • @ : 스크립트에 전달된 모든 명령줄 매개변수
  • $? : 마지막으로 실행된 프로세스의 종료 상태
  • $$ : 현재 스크립트의 프로세스 ID(PID)
  • $USER : 스크립트를 실행하는 사용자의 사용자 이름
  • $HOSTNAME : 스크립트를 실행하는 컴퓨터의 호스트 이름
  • $SECONDS : 스크립트가 실행된 시간(초)
  • $RANDOM : 난수
  • $LINENO : 스크립트의 현재 줄 번호

하나의 스크립트에서 이 모든 것을 보고 싶으신가요? 가능합니다! 다음 코드를 ‘special.sh’라는 텍스트 파일로 저장하세요.

#!/bin/bash
  echo "There were $# command line parameters"
  echo "They are: $@"
  echo "Parameter 1 is: $1"
  echo "The script is called: $0"
  pwd
  echo "pwd returned $?"
  echo "This script has Process ID $$"
  echo "The script was started by $USER"
  echo "It is running on $HOSTNAME"
  sleep 3
  echo "It has been running for $SECONDS seconds"
  echo "Random number: $RANDOM"
  echo "This is line number $LINENO of the script"

다음 명령어를 입력하여 스크립트를 실행 가능하게 만드세요.

chmod +x special.sh

이제 아래와 같이 다양한 명령줄 매개변수를 사용하여 스크립트를 실행할 수 있습니다.

환경 변수

Bash는 환경 변수를 사용하여 시작할 때 생성되는 환경의 속성을 정의하고 기록합니다. 사용자 이름, 로케일, 히스토리 파일에 저장할 수 있는 명령어 수, 기본 편집기 등의 정보를 Bash는 쉽게 접근할 수 있도록 환경 변수에 저장합니다.

Bash 세션에서 활성화된 환경 변수를 보려면 다음 명령어를 사용하십시오.

env | less

목록을 스크롤하면서 스크립트에서 유용하게 사용할 수 있는 환경 변수들을 찾아보세요.

변수 내보내기

스크립트는 실행될 때 자체 프로세스에서 실행되며, 스크립트에서 사용하는 변수는 해당 프로세스 외부에서는 보이지 않습니다. 스크립트가 다른 스크립트와 변수를 공유하려면 해당 변수를 ‘내보내기(export)’ 해야 합니다. 두 개의 스크립트를 사용하여 이 작업을 수행하는 방법을 보여드리겠습니다.

먼저 다음 코드를 ‘script_one.sh’ 파일로 저장합니다.

#!/bin/bash
  first_var=alpha
  second_var=bravo
  echo "$0: first_var=$first_var, second_var=$second_var"
  export first_var
  export second_var
  ./script_two.sh
  echo "$0: first_var=$first_var, second_var=$second_var"

이 스크립트는 ‘first_var’와 ‘second_var’라는 두 개의 변수를 만들고 값을 할당합니다. 터미널 창에 값을 출력한 다음 변수를 내보내고 ‘script_two.sh’를 호출합니다. ‘script_two.sh’가 종료되고 흐름이 이 스크립트로 돌아오면 변수를 다시 터미널 창에 출력합니다. 이를 통해 변수가 변경되었는지 확인할 수 있습니다.

두 번째로 사용할 스크립트는 ‘script_two.sh’입니다. 이 스크립트는 ‘script_one.sh’에서 호출하는 스크립트입니다. 다음 코드를 입력합니다.

#!/bin/bash
  echo "$0: first_var=$first_var, second_var=$second_var"
  first_var=charlie
  second_var=delta
  echo "$0: first_var=$first_var, second_var=$second_var"

이 스크립트는 두 변수의 값을 출력하고 새로운 값을 할당한 다음 다시 출력합니다.

이 스크립트들을 실행하려면 다음 명령어를 입력하여 실행 가능하게 만들어야 합니다.

chmod +x script_one.sh
  chmod +x script_two.sh

이제 다음 명령어를 입력하여 ‘script_one.sh’를 실행합니다.

./script_one.sh

출력 결과는 다음과 같습니다.

  • script_one.sh는 alpha와 bravo인 변수 값을 출력합니다.
  • script_two.sh는 변수 값을 그대로 받아서 출력합니다.
  • script_two.sh는 변수 값을 charlie와 delta로 변경합니다.
  • script_one.sh는 여전히 alpha와 bravo인 변수 값을 출력합니다.

두 번째 스크립트에서 발생하는 일은 해당 스크립트 내에서만 유효합니다. 마치 변수 사본이 두 번째 스크립트로 전달되고 해당 스크립트가 종료되면 삭제되는 것과 같습니다. 첫 번째 스크립트의 원래 변수는 두 번째 스크립트의 사본에서 발생하는 어떤 변경에도 영향을 받지 않습니다.

변수 인용 방법

스크립트가 변수를 참조할 때는 큰따옴표(“)를 사용하여 참조해야 합니다. 이를 통해 변수를 올바르게 참조할 수 있으며, 스크립트가 실행될 때 변수 값이 사용됩니다.

변수에 할당하는 값에 공백이 포함되어 있으면, 변수에 값을 할당할 때 공백을 따옴표로 묶어야 합니다. 기본적으로 Bash는 공백을 구분 기호로 사용하기 때문입니다.

다음은 예시입니다.

site_name=How-To Geek

Bash는 “Geek” 앞의 공백을 새로운 명령어가 시작됨을 의미하는 것으로 해석합니다. 해당 명령어가 없다고 오류 메시지를 표시하고 해당 줄을 무시합니다. ‘echo’ 명령어를 사용해 ‘site_name’ 변수의 값을 출력해 보면 ‘How-To’ 텍스트조차도 포함되지 않은 것을 알 수 있습니다.

아래와 같이 값 주위에 큰따옴표를 사용하여 다시 시도해 보세요.

site_name="How-To Geek"

이번에는 하나의 값으로 인식되어 ‘site_name’ 변수에 올바르게 할당됩니다.

‘echo’ 명령어 활용

명령어 대체, 변수 인용, 달러 기호 사용 시점을 기억하는 데는 시간이 걸릴 수 있습니다.

Enter 키를 눌러 Bash 명령줄을 실행하기 전에 ‘echo’ 명령어를 앞에 붙여서 미리 실행해 보세요. 이를 통해 어떤 일이 일어날지 예측하고 실수를 방지할 수 있습니다. 또한 구문에서 범할 수 있는 실수를 사전에 잡을 수 있습니다.