나는 이미 아래 방법이 여러 번 작동하는 방식과 방법에 대해 이미 논의 했으므로 다시는하지 않을 것입니다. 개인적으로이 주제에 대한 저의 즐겨 찾기는 여기 와 여기에 있습니다 .
읽는 것에 관심이 없지만 여전히 궁금한 점은 함수의 입력에 첨부 된 here-docs 가 함수가 실행 되기 전에 쉘 확장에 대해 평가 되고 함수가 정의 된 상태에서 새로 생성되었다는 것을 이해하십시오. 함수가 호출 될 때 마다
알리다
다른 함수를 선언하는 함수 만 있으면됩니다.
_fn_init() { . /dev/fd/4 ; } 4<<INIT
${1}() { $(shift ; printf %s\\n "$@")
} 4<<-REQ 5<<-\\RESET
: \${_if_unset?shell will ERR and print this to stderr}
: \${common_param="REQ/RESET added to all funcs"}
REQ
_fn_init $(printf "'%s' " "$@")
RESET
INIT
IT 운영
여기서는 _fn_init
이라는 함수를 선언하도록 요청합니다 fn
.
set -vx
_fn_init fn \
'echo "this would be command 1"' \
'echo "$common_param"'
#OUTPUT#
+ _fn_init fn 'echo "this would be command 1"' 'echo "$common_param"'
shift ; printf %s\\n "$@"
++ shift
++ printf '%s\n' 'echo "this would be command 1"' 'echo "$common_param"'
printf "'%s' " "$@"
++ printf ''\''%s'\'' ' fn 'echo "this would be command 1"' 'echo "$common_param"'
#ALL OF THE ABOVE OCCURS BEFORE _fn_init RUNS#
#FIRST AND ONLY COMMAND ACTUALLY IN FUNCTION BODY BELOW#
+ . /dev/fd/4
#fn AFTER _fn_init .dot SOURCES IT#
fn() { echo "this would be command 1"
echo "$common_param"
} 4<<-REQ 5<<-\RESET
: ${_if_unset?shell will ERR and print this to stderr}
: ${common_param="REQ/RESET added to all funcs"}
REQ
_fn_init 'fn' \
'echo "this would be command 1"' \
'echo "$common_param"'
RESET
필수
이 함수를 호출하려면 환경 변수 _if_unset
가 설정되어 있지 않으면 죽습니다 .
fn
#OUTPUT#
+ fn
/dev/fd/4: line 1: _if_unset: shell will ERR and print this to stderr
쉘 추적의 순서에 유의하십시오. 설정이 해제 fn
되었을 때 호출 될 때 실패 할 _if_unset
뿐만 아니라 처음부터 실행되지 않습니다 . 이것은이 문서 확장 작업을 할 때 이해해야 할 가장 중요한 요소입니다. 결국에는 반드시 확장이 먼저 이루어져야합니다 <<input
.
/dev/fd/4
상위 쉘이 입력을 함수로 전달하기 전에 해당 입력을 평가하고 있기 때문에 오류가 발생 합니다. 필수 환경을 테스트하는 가장 단순하고 효율적인 방법입니다.
어쨌든 실패는 쉽게 해결됩니다.
_if_unset=set fn
#OUTPUT#
+ _if_unset=set
+ fn
+ echo 'this would be command 1'
this would be command 1
+ echo 'REQ/RESET added to all funcs'
REQ/RESET added to all funcs
융통성 있는
변수 common_param
는로 선언 된 모든 함수에 대해 입력시 기본값으로 평가됩니다 _fn_init
. 그러나 그 가치는 다른 것으로도 변경 될 수 있으며, 마찬가지로 선언 된 모든 기능에 의해 존중 될 것입니다. 나는 이제 껍질 흔적을 남기지 않을 것입니다-우리는 여기서 미지의 영역으로 들어 가지 않을 것입니다.
set +vx
_fn_init 'fn' \
'echo "Hi! I am the first function."' \
'echo "$common_param"'
_fn_init 'fn2' \
'echo "This is another function."' \
'echo "$common_param"'
_if_unset=set ;
위의 두 함수를 선언하고 설정 _if_unset
합니다. 이제 두 함수 중 하나를 호출하기 전에 설정을 해제 common_param
하여 호출 할 때 스스로 설정한다는 것을 알 수 있습니다.
unset common_param ; echo
fn ; echo
fn2 ; echo
#OUTPUT#
Hi! I am the first function.
REQ/RESET added to all funcs
This is another function.
REQ/RESET added to all funcs
그리고 이제 발신자의 범위에서 :
echo $common_param
#OUTPUT#
REQ/RESET added to all funcs
그러나 이제는 그것이 완전히 다른 것이기를 원합니다.
common_param="Our common parameter is now something else entirely."
fn ; echo
fn2 ; echo
#OUTPUT#
Hi! I am the first function.
Our common parameter is now something else entirely.
This is another function.
Our common parameter is now something else entirely.
그리고 내가 설정을 해제하면 _if_unset
?
unset _if_unset ; echo
echo "fn:"
fn ; echo
echo "fn2:"
fn2 ; echo
#OUTPUT#
fn:
dash: 1: _if_unset: shell will ERR and print this to stderr
fn2:
dash: 1: _if_unset: shell will ERR and print this to stderr
초기화
언제든지 기능 상태를 재설정해야하는 경우 쉽게 수행 할 수 있습니다. 함수 내에서만 수행하면됩니다.
. /dev/fd/5
5<<\RESET
입력 파일 설명자 에서 함수를 처음 선언하는 데 사용되는 인수를 저장했습니다 . 따라서 .dot
언제든지 쉘에서 소스를 소싱하면 처음에 설정 프로세스를 반복합니다. POSIX가 실제로 파일 디스크립터 장치 노드 경로를 지정하지 않는다는 사실을 간과하고 싶다면 셸의 필수 요소입니다 .dot
.
이 동작을 쉽게 확장하고 기능에 대해 다른 상태를 구성 할 수 있습니다.
더?
그건 그렇고, 표면을 거의 긁지 않습니다. 필자는 종종 이러한 기술을 사용하여 언제든지 선언 할 수있는 작은 도우미 함수를 기본 함수의 입력 (예 $@
: 필요에 따라 추가 위치 배열)에 삽입 할 수 있습니다. 사실-내가 믿는 것처럼, 고차 껍질이 어쨌든하는 것은 이것과 매우 가까운 것이어야합니다. 프로그래밍 방식으로 이름이 매우 쉽게 표시됩니다.
또는 인 - 라인 기능 - - 또한 같은 I 파라미터의 한정된 유형을 수용하고 람다의 라인을 따라 단일 용도 또는 다른 범위 제한 버너 함수를 정의하는 생성 함수를 선언 단순히 그 unset -f
'자체 때 S는 을 통하여. 쉘 함수를 전달할 수 있습니다.