모양
greet() {
local name="${1:?name required}"
echo "hi, $name"
}
greet Alice함수도 $1, $2, $@, $#로 인자를 받아. bash나 zsh에서는 작업용 변수를 local로 선언해 호출한 쪽의 같은 이름을 덮어쓰지 않게 해.
반환 값
return N은 함수의 종료 상태를 정하며 보통 0은 성공, 그 밖의 값은 실패를 뜻해. 문자열 결과가 필요하면 표준 출력으로 내보내고 명령 치환으로 받을 수 있지만, 로그까지 표준 출력에 섞으면 결과가 오염돼.
upper() { echo "${1^^}"; } # bash 4 이상
name="$(upper hello)"변수 범위에서 생기는 함정
# 문제: 호출한 쪽의 tmp를 덮어씀
f() { tmp=42; echo $tmp; }
tmp=hello
f # 42
echo $tmp # hello가 아니라 42가 출력됨
# 수정
f() { local tmp=42; echo $tmp; }함수를 자식 셸에 전달할 때
현재 셸에 정의한 함수는 기본적으로 자식 프로세스에서 보이지 않아. bash에서는 export -f myfunc로 자식 bash에 내보낼 수 있지만 zsh의 동작은 다르고, 대부분의 스크립트에는 이 기능이 필요하지 않아.
라이브러리 스크립트
도우미를 lib.sh에 모아 source하면 현재 셸에 함수가 들어와. 다만 호출한 현재 디렉터리는 언제든 달라질 수 있으므로 무조건 source ./lib.sh라고 쓰기보다, 실행 파일 자신의 위치를 기준으로 경로를 계산하는 편이 안전해.
표준 출력은 함수의 데이터 통로야
value=$(lookup key)처럼 값을 받는 함수라면 표준 출력에는 결과만 써. 진행 상황과 진단 메시지는 >&2로 표준 오류에 보내야 호출자가 데이터를 안전하게 캡처할 수 있어. 셸 함수의 ‘반환값’은 문자열이 아니라 종료 상태라는 구분을 지키면 조합이 쉬워져.
라이브러리를 불러오는 것도 실행이야
source는 파일 내용을 현재 셸에서 그대로 실행해. 믿을 수 없는 파일을 불러오면 명령도 함께 실행되고 변수와 옵션도 바뀔 수 있어. 공용 라이브러리는 로드 시 부작용을 만들지 말고 함수 정의와 상수 설정에 집중해.