23장. 함수

차례
23.1. 복잡 함수와 함수의 복잡성(Complex Functions and Function Complexities)
23.2. 지역 변수와 재귀 함수(Local Variables and Recursion)

어느 정도 제한은 있지만 Bash도 "실제" 프로그래밍 언어들처럼 함수를 지원합니다. 함수란 서브루틴으로, 어떤 동작들이 구현된 코드 블럭이고, 특정한 일을 수행하는 "블랙 박스"입니다. 반복적인 코드나 약간만 다른 일을 반복하는 작업들이 있다면 함수를 쓰도록 고려해 보는 것이 좋습니다.

function function_name {
command...
}

혹은

function_name () {
command...
}

두 번째 형태는 C 프로그래머들에게 아주 반가울 것입니다(또한 이 형태가 더 이식성 있습니다).

C 함수 문법과 더욱 비슷하게 왼쪽 중괄호를 다음 줄에 놓아도 됩니다.

function_name ()
{
command...
}

함수는 간단하게 함수 이름을 불러서 실행시킬 수 있습니다.

예 23-1. 간단한 함수

#!/bin/bash

funky ()
{
  echo "funky 함수입니다."
  echo "funky 함수를 빠져 나갑니다."
} # 함수가 불리기 전에 선언돼 있어야 합니다.

  # 이제 함수를 부릅시다.

funky

exit 0

함수는 함수가 불리기 전에 정의되어야 됩니다. 예를 들어 C에서 처럼 함수를 미리 "선언"하는 방법은 없습니다.
# f1
# "f1"이 아직 정의되지 않았기 때문에 에러 메세지가 나옵니다.

# 그렇지만...


f1 ()
{
  echo "\"f1\" 함수에서 \"f2\" 함수 부르기."
  f2
}


f2 ()
{
  echo "\"f2\" 함수."
}

f1  # "f2" 함수는 정의되기 전에 참조되지만 실제로는 여기 전에는
    # 불리지 않기 때문에 가능합니다.
    
# Thanks, S.C.

함수 안에서 다른 함수를 정의하는게 가능하긴 하지만 그렇게 쓸모가 있진 않습니다.
f1 ()
{

  f2 () # 중첩됨.
  {
    echo "함수 \"f1\"속의 함수 \"f2\"."
  }

}

# f2
# 에러가 납니다.

f1  # "f1"이 자동으로 "f2"를 부르지 않기 때문에 아무 일도 일어나지 않습니다.
f2  # "f1"을 부름으로써 "f2"의 정의가 이루어졌기 때문에 이제는 "f2"를 불러도 괜찮습니다.

# Thanks, S.C.

함수 선언은 명령어가 아니면 안 돼 보이는 곳에서 조차 가능합니다.
ls -l | foo() { echo "foo"; }  # 가능하지만 쓸모 없습니다.



if [ "$USER" = bozo ]
then
  bozo_greet ()   # if/then 문 중간에 들어간 함수 정의.
  {
    echo "Hello, Bozo."
  }
fi

bozo_greet        # bozo 사용자일 때만 동작하고 다른 사용자는 에러가 납니다.



# 어떤 상황에서는 다음처럼 하는 것이 유용할 때가 있습니다.
NO_EXIT=1   # 밑에 나올 함수 정의를 가능하게 해 줍니다.

[[ $NO_EXIT -eq 1 ]] && exit() { true; }     # "and-list" 안에서 함수를 정의.
# $NO_EXIT 가 1이라면 "exit ()"를 선언.
# "true"로 별칭(alias)을 걸어서 내장 명령어인 "exit"를 끕니다.

exit  # 내장 명령어인 "exit"를 부르지 않고 "exit ()" 함수를 부릅니다.

# Thanks, S.C.