exit
서브 쉘에서 실행하는 것은 하나의 함정입니다.
#!/bin/bash
function calc { echo 42; exit 1; }
echo $(calc)
스크립트는 42를 인쇄 하고 리턴 코드 를 사용하여 서브 쉘 을 종료 1
한 후 스크립트를 계속합니다. 의 호출 echo $(CALC) || exit 1
코드를 바꾸더라도 도움이되지 않습니다.의 리턴 코드는의 리턴 코드에 echo
관계없이 0입니다 calc
. 그리고 calc
이전에 실행됩니다 echo
.
더 많은 수수께끼는 다음 스크립트와 같이 내장 exit
으로 감싸서 효과를 방해합니다 local
. 입력 값을 확인하는 함수를 작성할 때 문제를 우연히 발견했습니다. 예:
오늘의 "year month day.log"라는 파일을 만들고 싶습니다 20141211.log
. 날짜는 합리적인 가치를 제공하지 못하는 사용자에 의해 입력됩니다. 따라서 내 함수 fname
에서 반환 값 date
을 확인하여 사용자 입력의 유효성을 확인합니다.
#!/bin/bash
doit ()
{
local FNAME=$(fname "$1") || exit 1
touch "${FNAME}"
}
fname ()
{
date +"%Y%m%d.log" -d"$1" 2>/dev/null
if [ "$?" != 0 ] ; then
echo "fname reports \"Illegal Date\"" >&2
exit 1
fi
}
doit "$1"
좋아 보인다 스크립트 이름을 지정하십시오 s.sh
. 사용자가로 스크립트를 호출 ./s.sh "Thu Dec 11 20:45:49 CET 2014"
하면 파일 20141211.log
이 생성됩니다. 그러나 사용자 ./s.sh "Thu hec 11 20:45:49 CET 2014"
가을 입력하면 스크립트가 다음을 출력합니다.
fname reports "Illegal Date"
touch: cannot touch ‘’: No such file or directory
라인 fname…
은 잘못된 입력 데이터가 서브 쉘에서 감지되었다고 말합니다. 그러나 지시문이 항상 반환 하기 때문에 행 exit 1
의 끝에는 local …
트리거되지 않습니다 . 이는 이후 에 실행 되므로 리턴 코드를 겹쳐 쓰기 때문 입니다 . 그리고 그 때문에 스크립트는 계속 빈 매개 변수로 호출 됩니다. 이 예제는 간단하지만 bash 동작은 실제 응용 프로그램에서 상당히 혼란 스러울 수 있습니다. 실제 프로그래머는 현지인을 사용하지 않습니다 .☺local
0
local
$(fname)
touch
명확하게하려면 :이 없으면 local
유효하지 않은 날짜를 입력하면 스크립트가 예상대로 중단됩니다.
수정은 라인을 다음과 같이 분할하는 것입니다
local FNAME
FNAME=$(fname "$1") || exit 1
이상한 동작 local
은 bash의 맨 페이지에 있는 문서에 따릅니다 . "로컬이 함수 외부에서 사용되거나 유효하지 않은 이름이 제공되거나 name이 읽기 전용 변수가 아니면 리턴 상태는 0입니다."
버그는 아니지만 bash의 동작은 반 직관적이라고 생각합니다. local
그럼에도 불구하고 실행 순서를 알고 있지만 깨진 과제를 가리지 않아야합니다.
내 초기 답변에는 약간의 부정확성이 포함되어 있습니다. mikeserv와의 공개적이고 심도있는 토론 후 (고맙습니다) 나는 그들을 고치기 위해 갔다.