다음 함수는 선택적 디버깅, 상황에 맞는 도움말 등을 처리하기 위해 다른 모든 함수의 첫 번째 줄로 호출됩니다. 따라서 한 함수를 호출한 다음 다른 함수를 호출하면 순환 참조가 발생할 수 있으며 일반적으로 발생합니다.
기능을 잃지 않고 순환 참조를 피하는 방법은 무엇입니까?
function fnInit () {
###
### on return from fnInit...
### 0 implies "safe to continue"
### 1 implies "do NOT continue"
###
#
local _fn=
local _msg=
#
### handle optional debugging, context sensitive help, etc.
#
[[ "$INSPECT" ]] && { TIMELAPSE= ...; }
### fnInit --inspect
#
[[ "$1" == --help ]] && { ... ; return 1; }
### fnInit --help
# :
# :
return 0
}
답변1
함수 fnInit()(예: 현재 함수 - ${FUNCNAME[0]})도 함수 호출 스택에서 더 높은 곳에 나타나면 구제 조치를 취하세요.
아래 결과 버전에서 ...
- $_fna는 이를 호출한 함수(레벨 1 이상)부터 시작하여 함수 호출 스택에 공백으로 구분된 함수 이름 목록을 포함하는 문자열입니다.
- 이 관용구는
"${_fna/${FUNCNAME[0]}/}"
$_fna에서 현재 함수 이름을 뺍니다. [[ "${_fna/${FUNCNAME[0]}/}" != "${_fna}" ]]
빼기 결과가 원래 결과와 동일하면(아무 것도 빼지 않음) 비교 결과는 true(0)을 반환합니다.- 목록 처리 제어 연산자는
&&
이전 명령( )의 반환 코드가 true(0)인 경우에만[[ ... ]]
다음 명령이 실행된다는 의미입니다. { return 0; }
여기서는 하나의 명령만 실행되므로 return( ) 주위의 중괄호는 선택 사항입니다. 하지만그들은 필수입니다다른 모든 경우에는 일관성을 위해 일반적으로 넣습니다. 그것들이 없으면 연산자 우선 순위로 인해 이와 같은 작업은[[ ... ]] && dosomething; return 0
예상대로 true인 경우에만 실행됩니다.dosomething
[[ ... ]]
그러나 그것은 항상 구현될 것입니다return 0
.Bash는 이것을 다음과 같이 읽을 것입니다 ...[[ ... ]] && dosomething return 0
fnInit()
각 함수 호출은 한 번만 처리됩니다.
function fnInit () {
###
### on return from fnInit...
### 0 implies "safe to continue"
### 1 implies "do NOT continue"
###
local _fna="${FUNCNAME[*]:1}"; [[ "${_fna/${FUNCNAME[0]}/}" != "${_fna}" ]] && { return 0; }
### Detect circular reference
### Is function in the function call stack more than once?
###
### Seems like the following should work but it does not...
### if [[ "${FUNCNAME[*]:1/$FUNCNAME/}" != "${FUNCNAME[*]:1}" ]]; then ...
### It appears to fail silently and exit the script so neither 'then'
### nor 'else' branch executes.
### Why?
### per http://unix.stackexchange.com/q/186942/27437...
### In general, you can't use multiple variable expansion modifiers
### in the same expression. – Barmar
###
### Solution:
### Store the array into a temporary string variable.
###
#
local _fn=
local _msg=
#
### handle optional debugging, context sensitive help, etc.
#
[[ "$INSPECT" ]] && { TIMELAPSE= ...; }
### fnInit --inspect
#
[[ "$1" == --help ]] && { ... ; return 1; }
### fnInit --help
# :
# :
return 0
}
답변2
일반적으로 이는 상태 변수(플래그)를 확인하고 설정하여 수행됩니다. 그것은 마치 ...
function fnInit
{
[[ -z ${this_init_state} ]] || return 0
this_init_state=1
# rest of your code
}
(초기화 함수가 별도의 모듈에 있는 경우 dot 명령을 사용하여 해당 모듈을 가져옵니다.)