Bash 스크립팅에서 내가 겪은 어려운 일 중 하나는 변수 확장을 재귀적으로 사용하는 것입니다.
그러나 저는 [ChatGPT를 통해] 위치 매개변수 값을 참조하기 위해 간접 대체를 사용할 수 있다는 사실을 발견했습니다.
linkerArgs+=("${!i}")
그러나 문자열 대체를 사용하면 논리적으로 확장을 재귀적으로 사용할 수 있습니다.
"${x// /$newChar}"
bash 인터프리터가 배열에 항목을 할당하는 맥락에서 사용될 때 후자 유형의 확장(괄호 안의 달러 기호만)을 "잘못된 대체"로 처리하지만 문자열 대체에서는 사용할 때는 처리하지 않는 이유는 무엇입니까?
답변1
대신 구문의 다른 위치에 포함된 변수를 사용합니다. 계산 이름이 아니라 계산 매개변수입니다.
이는 고전적인 POSIX 대체와 함께 작동합니다(예: ${var#replacement}
Inside ) replacement
. 대체를 수행할 수 있습니다.
$ A=B
$ B=42
$ echo ${$A}
bash: ${$A}: bad substitution
$ echo ${!A}
42
하지만:
$ echo ${B}
42
$ echo ${B%2}
4
$ C=2
$ echo ${B%$C}
4
문법의 $C
텍스트와 마찬가지로 작동하는 것을 볼 수 있습니다.2
${B%<tail-pattern-to-chop>}
구문은 ${!A}
Bash 확장입니다. 왜 명확하지 않습니까 ${$A}
?
추측하기는 어렵습니다. 이것은 매우 오래된 Bash 기능입니다. bash-2.0
현재 Bash git 저장소의 시작 부분에 가져온 1996 tarball에 이미 존재합니다.
대조적으로, Make 언어는 계산된 변수를 사용하여 명백하게 수행합니다 $(OBJS_$(this_file))
.
이것은 순수한 추측이지만 문제가 될 수 있습니다. Make에서 계산된 변수를 보면 .NET $($(...
내부 에만 국한되지 않고 $(...)
어디에나 변수를 가질 수 있습니다.
로 대체된 ${$A}
셸에서 이것이 작동하는 것을 발견한 경우 변수를 계산하고 확장하여 유사한 기능이 작동할 것으로 예상하십시오 .A
B
${abc_$A}
abc_B
따라서 아마도 구현자/발명자는 ${!A}
그렇게까지 갈 의향이 없을 것입니다.
또 다른 가능성은 이 함수 앞에 다른 ${!
함수가 ${!name[@]}
이미 존재한다는 것입니다. 따라서 해당 구문을 기반으로 하며 뒤에 , 또는 이 오지 않을 ${!word}
때 의미가 부여됩니다 . 기존 확장의 구문에 새 확장을 통합하는 것은 기존 확장을 사용하는 프로그램에만 영향을 미칠 수 있는 문제에 대한 추론의 양을 줄여주기 때문에 쉽습니다.word
@
*
[*]
[@]
불행하게도 GNU의 FTP 저장소는 bash-1.14.7.tar.gz
타르볼과 bash-2.0.tar.gz
타르볼만 제공합니다. 그 사이에는 아무것도 없습니다. 버전 1.14.7에는 공식적인 확장이 없습니다 ${!...}
. 그 문제에 대해서는 아직 배열을 구현하지 않았습니다. 버전 2.0은 모든 ${!...}
구문을 ${!word}
구현 합니다 ${name[@]}
. 어떤 일이 먼저 일어났는지 알 수 있는 자세한 기록이 없습니다.
최후의 수단으로 쳇 레이미(Chet Raimi)를 인터뷰할 수 있습니다. 나는 대답이 다음과 같을 것이라고 생각합니다. 여러 확장이 변수 확장에 추가되고 간접 참조는 자체 구문을 얻는 대신 동일한 구문으로 고정됩니다. 즉, Bash가 볼 때 ${!
"이후 다양한 Bash 확장을 처리한다"는 의미입니다.