Linux/Shell Script

[Shell Script] Functions - 1

비번변경 2022. 7. 2. 22:28

Functions

{ ;}, ()를 이용해 명령 그룹을 만들면 같은 context에서 실행되어 명령 그룹 전체가 하나의 명령처럼 실행되는 것과 같은 화가를 가진다.

따라서 명령 그룹에 이름을 붙임으로써 함수를 정의하면 일반 명령과 동일하게 사용할 수 있다.

{ ;}는 현재 shell에서, ()은 subshell에서 실행되므로 보통 { ;}를 사용하여 함수를 정의한다.

 

# 파이프로 인해 subshell에서 실행되어 echo $var는 값이 표시되지 않는다.
echo hello world | read var; echo "$var"

# 명령 그룹을 만들면 read, echo 명령이 같은 context에서 실행되어 값이 표시된다.
echo hello world | { read var; echo "$var" ;}

명령 그룹 비교

 

 

함수 사용 방법

일반 명령과 동일하며, return 명령으로 종료 상태 값을 지정할 수 있다. subshell에서는 정의했던 함수를 별다른 설정 없이 사용할 수 있으나, 새로운 프로세스에서도 사용하기 위해서는 export -f를 이용해 함수를 export 해야 한다.

 

 

함수 정의 방법

Shell은 전달된 인자가 함수 내에서 특수 변수($1, $2, $3……)에 자동으로 할당되기 때문에 함수 정의 시 매개변수를 적지 않는다.

함수명에는 메타문자나 quotes 등은 사용할 수 없고, 외부 명령이나 alias와 같은 이름을 사용하는 경우에는 syntax error가 발생한다. 단, bash의 경우 function 키워드를 붙임으로써 에러를 방지할 수 있다.

# 문법
function_name () {
   commands
};

# bash에서 허용
function function_name() {
   commands
}

# 정의된 함수 내용 보기
declare -f <function_name>

# 현재 쉘에 정의된 모든 함수명 보기
declare -F
compgen -A function

# 특정 함수의 정의 여부 확인
declare -F <function_name>

# 정의된 함수 삭제
unset -f <function_name>

함수 정의 및 정의 여부 확인

 

함수는 실행하기 전에 정의되어 있어야 한다.

foo1            # 여기서는 foo1 함수 정의가 안되어있기 때문에 실행할 수 없다.

foo1() {
    echo "foo1"
    foo2
}
                # 여기서 foo1 함수를 실행할 수 있지만 foo1 함수내에 있는
foo1            # foo2 함수를 실행할수 없으므로 오류가 발생한다.

foo2() {
    echo "foo2"
}

foo1            # 여기서는 오류없이 foo1, foo2 함수가 모두 실행된다.

함수 실행 전 정의 필요

 

조건에 따라 다른 함수를 정의할 수 있다.

아래 스크립트는 KSH_VERSION이라는 변수가 설정되어 있으면, 첫번째 puts 함수가 정의되고, 그렇지 않으면 두 번째 puts 함수가 정의된다.

if test -n "$KSH_VERSION"; then
    puts() {
        print -r -- "$*"
    }
else
    puts() {
        printf '%s\n' "$*"
    }
fi

 

변수는 기본적으로 global하다.

변수는 source 한 파일을 포함해 현재 스크립트 내에서 global 하다.

변수 scope

 

local 명령으로 지역변수를 설정할 수 있다.

local과 declare은 같은 기능을 한다. 단, local은 global scope에서 사용할 수 없다. 또한 함수 내에서 declare가 사용되면 local과 동일하다.

지역 변수 사용

💡 local 변수는 unset 시 global 변수가 된다.
scope을 유지하면서 변숫값을 초기화할 때는 ""으로 초기화해야 한다.

 

Shell은 dynamic scoping을 사용한다.

함수에서 local로 선언한 변수는 child 함수에서 읽고 쓸 수 있다. child 함수에서 변경된 값은 parent 함수에 적용된다.

💡 dynamic scoping
함수 f1이 실행 중일 때 함수 f2에서 f1의 지역변수에 접근하는 것. sh, bash, powershell, emacs lisp 같은 언어에서 사용되고 있다.
보통 프로그래밍 언어는 lexical scoping(static scoping)을 사용하여 f2은 f1의 지역 변수에 접근할 수 없다.

dynamic scoping

 

 

참고 문서

https://mug896.github.io/bash-shell/functions.html

 

 

728x90