덕 타이핑 관련 중첩 문제:
function f1 { echo $1; } #with argument
function f2 { N=$((0+1)); f$N "fff"; } #with dynamic name
원하는 결과:
function f2 { { echo $1; } "fff"; }
알아채다. 죄송합니다. 실제 인코딩 문제로 질문을 수정했습니다.
문제를 해결하는 방법?
답변1
이것은 bash가 하는 일이 아닙니다. 이것도 아니다버팀대 확장. 그래서 저는 당신이 여기서 무엇을 하려는지 정말로 알고 싶습니다.
Bourne과 같은 쉘이 작동하는 방식은 호출될 때만 실제로 확장되는 호출 가능한 함수 테이블을 통해 작동합니다. 따라서 해석될 때 f1;
함수는 f1
"라고," 이전의 매크로가 아닌
그러므로 당신의원하는 결과위에 게시한 코드와는 거의 관련이 없으며 본질적으로 동일하지 않습니다. 함수에는 {…}
범위가 지정된 명령문 모음일 뿐만 아니라 중요한 고유한 컨텍스트와 기호가 있습니다 .
따라서 당신이 원하는 것은 배우자와 배우자가 작동하는 방식을 바꾸지 않고서는 불가능합니다 bash
. 이 시점에서 당신은 쉘 스크립팅보다 TeX에 더 가까운 다른 프로그래밍 언어를 사용하고 있습니다. (그런데, 언어로서의 TeX는...독창적이지만 좋은 면에서 지배적이지는 않습니다.)
따라서 귀하의 질문에 나와 있듯이 실제로는변화를 호출할 때 함수 목록에서 기호 조회를 수행하는 등 프로그램이 이전처럼 작동하지 않습니다 f1;
. 이로 인해 함수를 재정의하는 기능을 활용하는 좀 더 복잡한 스크립트가 중단될 수 있습니다.
나는 이것이 좋은 생각이라고 생각하지 않지만 그것은 당신의 선택입니다. 당신은변화 없는bash 스크립트용 파서, 쉘 구문을 이해할 수 있는 파서아니요프로그램을 실행합니다. 원칙적으로는 안타깝게도
POSIX 쉘 언어는 여러 수준에서 컴파일러 구성에 대한 기존 통념에 도전합니다. 쉘 언어는 정적 구문 분석을 위해 설계되지 않았지만 오히려 구문 분석과 확장 실행의 결합을 허용합니다.
특히 여기서 강조하는 것은 다음과 같습니다.
어휘 분석은 구문 분석 컨텍스트에 따라 달라집니다.및 평가 맥락,
(Y. Régis-Gianas, N. Jeannerod, R. Treinen:Morbig: POSIX 쉘용 정적 파서)
이는 일반적으로 말해서 귀하가할 수 없다정적 풀기 . 실행 시 무슨 일이 일어나고 있는지 f1
알아야 합니다 !f1
f2
POSIX 쉘 디자인아니요일관된 유형 시스템과 같은 것이 없는 정적 언어이기 때문에 이에 대해 보장할 수 없습니다. alias f1=f3
런타임에 프로그램의 내용을 변경하려면 an이 포함된 조건문이 필요합니다 ! (이 문제를 해결하기 위해 사용할 수 있는 다른 메커니즘이 많이 있습니다.) 즉, 실행 중 각 지점에서 실제로 "의미"가 무엇 f1
인지 알 수 있는 유일한 시간 이며 쉘의 전체 상태를 알아야 합니다(그리고 환경) .f2
f2
그러므로 하고 싶은 일을 하세요.넌 껍질이 되어야 해;bash를 수정하고 후크를 통해 특정 콘텐츠를 인쇄(저장 또는 로그)할 수 있는 확장 기능을 추가해야 합니다.
하지만 아마도 질문에서 요청한 것보다 훨씬 작은 것을 원할 수도 있습니다. 아마도 쉘 스크립트를 수정하고 싶지는 않지만 언제든지 쉘 스크립트에서 함수 정의를 인쇄하고 싶을 수도 있습니다. 이는 다음을 통해 declare
수행할 수 있습니다 .declare -fp f1
답변2
이것이 당신이 쫓는 것인가요?
사양을 좀 수정해봤습니다. 명령의 두 번째 인수에 해당하는 함수는 함수 fout으로 환경에 로드됩니다. 스크립트를 실행하면
. duck.sh <string> <function number>
함수는 상위 쉘의 환경에 로드됩니다. 출력에는 선택한 함수와 첫 번째 인수(있는 경우)를 기반으로 한 출력이 표시됩니다.
파일 duck.sh:
#!/bin/bash
function f1 { echo $1; } #with argument
function f2 { f1; echo "here2 "$1; }
function f3 { f1; f2; echo "The Third "$1; }
function expandInner {
while [[ $toExpand != "" ]]; do
while read -r line; do
getInner $line
done <<< $toExpand
toExpand=$(grep -w -o 'f[0-9]' <<< $inner)
done
}
function getInner {
tmpString=$(typeset -f $1)
tmpString=$(echo $tmpString | awk 'BEGIN{RS="}"; FS="{"} {print $2}')
inner=${inner/${line}/${tmpString}}
}
if [ -z "$2" ] ; then
N=$((0+1))
else
N=$2
fi
inner=$(echo $(typeset -f f$N) | awk 'BEGIN{RS="}"; FS="{"} {print $2}')
toExpand=$(grep -w -o 'f[0-9]' <<< $inner)
expandInner
echo "function fout { $inner ; echo \"fff\"; }" | tee ~/.tmp; source ~/.tmp; rm ~/.tmp
fout $1