[쉘 스크립트] 쉘 스크립트 기초 - 함수 (7)

업데이트:     Updated:

카테고리:

태그:

🎯함수

함수 정의

bash 쉘 스크립트에서 함수를 만들기 위해 사용할 수 있는 형식은 두 가지가 있다.

# 방법 1. 
function name {
    commands
}

# 방법 2.
name() {
    commands
}
  • name 속성은 함수에 지정할 고유한 이름을 정의한다. 스크립트에서 사용자가 정의하는 함수에는 고유한 이름을 지정해야 한다.
  • commands는 함수를 구성하는 하나 이상의 bash 쉘 명령이다. 함수를 호출할 때 bash 쉘은 보통의 스크립트처럼 함수에 나타나는 순서로 각 명령을 실행한다.

함수 호출

# 스크립트
#!/bin/bash

func1
function func1 {
  echo "This is an example of a function"
}
count=1
while [ $count -le 5 ]
do
  func1
  count=$[ $count + 1 ]
done
echo "This is the end of the loop"
func1
echo "Now This is the end of the script"

# 실행 결과
func1: command not found
This is an example of a function
This is an example of a function
This is an example of a function
This is an example of a function
This is an example of a function
This is the end of the loop
This is an example of a function
Now This is the end of the script
  • 스크립트에서 func1 함수 이름을 참조할 때마다 bash 쉘은 func1 함수안에 정의된 명령을 실행한다.
  • 함수가 정의되기 전에 이를 사용하려고 하면 오류 메시지가 나타난다.

함수 리턴

bash 쉘에서 함수의 종료 상태를 만드는 방법에는 세 가지가 있다.

  1. 기본 종료
  2. return 명령 사용하기
  3. 함수 출력 이용하기

기본 종료

기본적으로 함수의 종료 상태는 함수의 마지막 명령이 돌려주는 종료 상태다.

# 스크립트
#!/bin/bash

func1() {
    echo "trying to display a non-existent file"
    ls -l badfile
}
echo "testing the function: "
func1
echo "The exit status is: $?"

# 실행 결과
testing the function: 
trying to display a non-existent file
ls: cannot access 'badfile': No such file or directory
The exit status is: 2
  • 함수의 마지막 명령이 실패했기 때문에 함수의 종료 상태는 0이 아니다.
  • 함수의 종료 상태를 결정하는데에 echo문은 영향을 주지 않는다. 오직 마지막 명령의 결과가 함수의 종료 상태를 의미한다.

return 명령 사용하기

bash쉘은 함수가 특정한 종료 상태를 돌려줄 수 있도록 return 명령을 사용할 수 있다. return 함수로 종료 상태를 정의하는 단일한 정수값을 사용한다.

# 스크립트
#!/bin/bash

function dbl {
  read -p "Enter a value: " value
  echo "doubling the value"
  return $[ $value * 2 ]
}
dbl
echo "The new value is $?"

# 실행 결과
Enter a value: 2
doubling the value
The new value is 4
  • dbl 함수는 사용자가 입력한 정수값을 $value 변수에 저장하고 이를 두 배로 만든다.
  • return 명령은 함수의 종료 상태를 돌려주므로 스크립트는 $? 특수 변수의 결과로 입력한 값의 2배한 결과를 표시한다.
  • return 명령을 사용할 때에 주의할 점이 몇 가지 있다.
    • $? 변수를 사용하여 함수의 값을 얻기 전에 다른 명령을 실행하면 함수의 반환값을 잃어버리게 된다. $? 변수는 마지막으로 실행된 명령의 종료 상태를 돌려준다는 점을 잊지 말아야 한다.
    • 종료 상태는 0에서 255의 범위 안에 있어야 한다. 종료 상태는 256보다 작아야 하므로 함수의 결과는 256보다 작은 정수값이어야 한다. 그 이상의 값은 255로 모듈러 연산한 값으로 변환된다.

함수 출력 이용하기

명령의 출력을 쉘 변수에 저장할 수 있는 것처럼 함수의 출력도 쉘 변수에 저장할 수 있따. 변수에서 나온 어떤 유형의 출력이든 변수에 할당하면 된다. 이 방법은 return 명령에서 256 이상의 값을 반환할 수 없는 한계를 보완할 수 있다.

# 스크립트
#!/bin/bash

function dbl {
  read -p "Enter a value: " value
  echo $[ $value * 2 ]
}
result=$(dbl)
echo "The new value is $result"

# 실행 결과
Enter a value: 2
The new value is 4
  • 새로운 함수는 이제 계산 결과를 표시하는 echo 문을 사용한다. 스크립트는 답을 받기 위해 종료 상태 대신 dbl 함수의 출력을 저장한다.
  • read 명령에서 사용자에게 묻는 짧은 메시지는 출력의 결과에 포함되지 않는다.

함수 매개변수

함수는 커맨드라인에서 함수에 전달되는 매개변수를 대신하기 위한 표준 매개 변수 환경 변수를 사용할 수 있다. 예를 들어, 함수의 이름은 $0 변수로 정의되고 함수의 커맨드라인에 있는 모든 매개변수는 $1, $2와 같은 변수로 정의된다. 또한 함수에 전달된 매개변수의 수를 결정하기 위한 특수한 변수 $#도 사용할 수 있다.

# 스크립트
#!/bin/bash

function addem {
  if [ $# -eq 0 ] || [ $# -gt 2 ]
  then
    echo -1
  elif [ $# -eq 1 ]
  then
    echo $[ $1 + $1 ]
  else
    echo $[ $1 + $2 ]
  fi
}

echo -n "Adding 10 and 15: "
value=$(addem 10 15)
echo $value

echo -n "Let's try adding just one number: "
value=$(addem 10)
echo $value

echo -n "Now trying adding no numbers: "
value=$(addem)
echo $value

echo -n "Finally, try adding three numbers: "
value=$(addem 10 15 20)
echo $value

# 실행 결과
Adding 10 and 15: 25
Let's try adding just one number: 20
Now trying adding no numbers: -1
Finally, try adding three numbers: -1
  • 스크립트에 있는 addem 함수는 먼저 스크립트가 전달한 매개변수의 수를 확인 한다.
  • 매개변수가 없거나 매개변수가 2개 보다 많다면 addem 함수는 -1을 돌려준다.
  • 매개변수가 하나만 있다면 addem 함수는 이 매개변수를 2배로 만들어서 결과값으로 사용한다.
  • 매개변수가 2개 있다면 addem 함수는 두 변수를 더해서 결과값으로 사용한다.

함수에서 변수의 범위

변수의 범위란, 변수가 보이는 곳을 뜻한다. 함수에 정의된 변수는 두 종류로 나뉜다.

  • 전역 변수
  • 지역 변수

전역 변수

전역 변수는 쉘 스크립트 안이라면 어디서나 쓸 수 있는 변수다. 기본적으로 스크립트에서 정의한 모든 변수는 전역 변수다. 스크립트의 메인 부분에서 변수를 정의했는지 함수 안에서 변수를 정의했는지는 중요하지 않다.

# 스크립트
#!/bin/bash

function dbl {
  value=$[ $value * 2 ]
}
read -p "Enter a value: " value
dbl
echo "The new value is: $value"

# 실행 결과
Enter a value: 2
The new value is: 4
  • value 변수는 함수 밖에서 정의되었고 함수 밖에서 값이 할당되었다.
  • dbl 함수가 호출될 때 함수 밖에서 정의된 value 변수가 참조된다.
  • 함수 안에서 value 변수가 재 할당된다.
  • 함수 밖에서 재 할당된 value 변수를 참조한다.

지역 변수

함수에서 전역 변수를 사용하는 대신 함수 안에서 사용되는 모든 변수를 지역 변수로 선언할 수 있다. 이를 위해서는 변수 선언 앞에 local 키워드를 사용하면 된다.

# 스크립트
#!/bin/bash

function func1 {
  local temp=$[ $value + 5 ]
  result=$[ $temp * 2 ]
  echo "Here is inside the function....."
  echo "The temp is $temp"
}
temp=4
value=6
func1
echo "Here is outside the function....."
echo "The result is $result"
echo "The temp is $temp"

# 실행 결과
Here is inside the function.....
The temp is 11
Here is outside the function.....
The result is 22
The temp is 4

func1 함수 안에서 $temp 변수를 변경해도 메인 스크립트 안에 있는 $temp 변수에 할당된 값에는 영향을 주지 않았다.

라이브러리 만들기

bash 쉘은 함수에 대한 라이브러리 파일을 만들어서 어떤 스크립트에서나 해당 라이브러리 파일을 가져와 쓸 수 있도록 기능을 제공한다. 다음은 간단한 라이브러리 파일을 만들고 이를 활용하는 예제이다.

  1. 먼저 세 가지 간단한 함수를 정의하는 myfunc라는 간단한 공용 라이브러리 파일을 만든다.
     function add {
     echo $[ $1 + $2 ]
     }
    
     function mul {
     echo $[ $1 * $2 ]
     }
    
     function div {
     if [ $2 -ne 0 ]
     then
         echo $[ $1 / $2 ]
     else
         echo -1
     fi
     }
    
  2. 다음 단계는 스크립트 파일에 myfunc 라이브러리 파일을 포함시키는 것이다. 하지만 문제가 있다.
    • 쉘 함수의 범위는 이를 정의한 쉘 세션 안에서만 유효하다.
    • myfunc 스크립트를 실행시킨다면 쉘은 새로운 쉘을 만들고 그 새로운 쉘에서 스크립트를 실행한다.
        # 스크립트
        #!/bin/bash
      
        ./myfunc
        result=$(add 10 15)
        echo "The result is $reulst"
      
        # 실행 결과
        add: command not found
        The result is    
      
    • 이 문제를 해결할 방법은 source 명령이다. source 명령은 새로운 쉘을 실행시키는 대신 현재 쉘 안에서 명령을 실행시킨다.
    • 쉘 스크립트 안에서 라이브러리 파일의 스크립트를 실행하기 위해 source 명령을 사용한다. 이렇게 하면 스크립트 안에서 함수를 사용할 수 있다.
        # 스크립트
        #!/bin/bash
      
        source ./myfunc
      
        value1=10
        value2=5
        result1=$(add $value1 $value2)
        result2=$(mul $value1 $value2)
        result3=$(div $value1 $value2)
      
        echo "The result of adding them is: $result1"
        echo "The result of multiplying them is: $result2"
        echo "The result of dividing them is: $result3"
      
        # 실행 결과
        The result of adding them is: 15
        The result of multiplying them is: 50
        The result of dividing them is: 2
      
  3. 스크립트는 myfunc 라이브러리 파일에 정의된 함수를 성공적으로 사용했다.

커맨드라인에서 함수 만들기

첫 번째 방법은 함수 정의를 모두 한 줄에 놓는 것이다. 이때 각 명령을 어디에서 구분해야 하는지를 쉘이 알 수 있도록 각 명령의 끝에 세미콜론을 두어야 한다.

$ function doubleit { read -p "Enter value: " value; echo $[ $value * 2 ]; }
$ doubleit
Enter value: 20
40

두 번째 방법은 여러 줄에 걸쳐서 함수를 정의하는 것이다. 이 방법에서 bash쉘은 더 많은 명령을 요구하기 위해 보조 프롬프트를 사용한다. 이때 각 명령의 마지막에 세미콜론을 둘 필요는 없어지고 단순히 키를 누르면 된다.

$ function doubleit {
> read -p "Enter value: " value
> echo $[ $value * 2 ]
> }
$ doblelit
Enter value: 20
40

.bashrc 파일에서 함수 정의하기

커맨드라인에서 직접 쉘 함수를 정의하는 방법의 커다란 단점은 쉘을 종료할 때 함수도 사라진다는 것이다. 더 간단한 방법은 쉘이 새로운 쉘을 시작할 때마다 불러들이는 파일에 함수를 정의하는 것이다.

이를 위한 가장 좋은 장소는 .bashrc 파일이다. bash 쉘은 대화형이든 기존 쉘 안에서 새로운 쉘을 시작하든, 쉘이 새로 시작될 때마다 홈 디렉토리에서 이 파일을 찾는다.

이 방법을 잘 활용하면 우리가 정의한 라이브러리 혹은 다른 사람이 작성한 라이브러리 파일을 쉘을 시작할 때 마다 불러들일 수 있다. .bashrc 스크립트에 source 명령으로 존재하는 라이브러리 파일을 더해보자!!

# .bashrc
source {라이브러리 path}

📖출처

리처드 블룸, 크리스틴 브레스, ⌜리눅스 커맨드라인 쉘 스크립트 바이블⌟, 스포트라잇북(2016)


👍 개인 공부 기록용 블로그입니다. 오류나 조언이 있으시면 언제든지 댓글 혹은 메일로 남겨주시면 감사하겠습니다! 😄

맨 위로 이동하기

Linux 카테고리 내 다른 글 보러가기

댓글남기기