~에서https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
매개변수 확장의 기본 형태는 입니다
${parameter}
. ...인수의 첫 번째 문자가 느낌표(
!
)인 경우 1단계 변수 간접 지정이 도입됩니다. Bash는 나머지 인수로 구성된 변수 값을 변수 이름으로 사용합니다. 그런 다음 해당 변수를 확장하고 인수 자체의 값이 아닌 나머지 대체에 해당 값을 사용합니다. 이를 간접 확장이라고 합니다. 아래에 설명된 확장은 예외입니다${!prefix}
.${!name[@]}
느낌표는 간접적인 관계를 소개하기 위해 여는 중괄호 바로 뒤에 와야 합니다....
${!prefix*} ${!prefix@}
IFS 특수 변수의 첫 번째 문자로 구분된 이름이 접두사로 시작하는 변수 이름으로 확장됩니다. "@"를 사용하고 큰따옴표 안에 확장이 발생하면 각 변수 이름이 별도의 단어로 확장됩니다.
${!name[@]} ${!name[*]}
name이 배열 변수인 경우 name에 할당된 배열 인덱스(키) 목록으로 확장됩니다. name이 배열이 아닌 경우 name 설정 시 0으로 확장되고, 그렇지 않으면 null로 확장됩니다. "@"을 사용하고 큰따옴표 안에 확장이 발생하면 각 키가 별도의 단어로 확장됩니다.
당신이 인용한 구절의 몇 가지 예를 들어주실 수 있나요? 나는 그들이 무엇을 의미하는지 모른다.
답변1
우리는 다음을 비교하고 차별화해야 합니다.
"${Var}" # Plain variable
"${!Var}" # Indirect expansion
"${!Var@}" # Prefix expansion
"${!Var[@]}" # Array keys expansion
"${Var[@]}" # Plain array expansion
*
매우 유사하지만 미묘한 차이점이 있는 확장 프로그램 도 있습니다 .
간접적인
간접적인 예:
$ varname=var_one
$ var_one=a-value
$ echo "${varname}"
var_one
$ echo "${!varname} and ${var_one}"
a-value and a-value
접두사
접두사 예:
$ head_one=foo
$ head_two=bar
$ printf '<%s> ' "${!head@}"
<head_one> <head_two>
$ printf '<%s> ' "${!head*}"
<head_one head_two>
변수는 기본적으로 공백인 IFS의 첫 번째 문자로 서로 붙어 있습니다( Space Tab NewLine기본적으로 IFS와 마찬가지로).
일반 배열
@
합계 의 작은(그러나 중요한) 차이를 보여주는 배열 예(사용되지 않음!) *
:
$ Array[1]=This
$ Array[2]=is
$ Array[3]=a
$ Array[4]=simple
$ Array[5]=test.
$ printf '<%s> ' "${Array[@]}"
<This> <is> <a> <simple> <test.>
$ printf '<%s> ' "${Array[*]}"
<This is a simple test.>
IFS에 대한 동일한 의견이 여기에도 적용됩니다.
저는 (의도적으로) 배열의 인덱스 0을 할당하지 않았습니다.
배열을 할당하는 더 쉬운 방법은 다음과 같습니다.
$ Array=( "" This is a simple test.)
하지만 여기서는 인덱스 0을 사용해야 하고, 저는 null 값(위의 unset 값과 다름)을 사용했습니다.
배열 목록
이 목적을 위해 간단한 인덱스 배열(숫자 포함)은 덜 흥미롭습니다.
$ Array=( "" A simple example of an array.)
$ printf '<%s> ' "${!Array[@]}"
<0> <1> <2> <3> <4> <5> <6>
$ printf '<%s> ' "${!Array[*]}"
<0 1 2 3 4 5 6>
그러나 연관 배열을 사용하면 상황이 더욱 흥미로워집니다.
$ unset Array # erase any notion of variable array.
$ declare -A Array # make it associative
$ Array=([foo]=one [bar]=two [baz]=three) # give it values.
$ printf '<%s> ' "${Array[@]}"
<two> <three> <one> # List of values.
$ printf '<%s> ' "${!Array[@]}"
<bar> <baz> <foo> # List of keys
$ printf '<%s> ' "${Array[*]}"
<two three one> # One string of list of values.
$ printf '<%s> ' "${!Array[*]}"
<bar baz foo> # One string of list of keys.
배정된 순서와 순서가 다르므로 주의하세요.
노트:내가 생각해낸 모든 사용법은 인용되거나 "${!Array[@]}"
인용되지 않았 ${!Array[@]}
으며 ${!Array[*]}
정확히 동일하게 작동하여 동일한 출력(Bash에서)을 제공합니다.
그러나 IFS 값에 대한 셸 분할의 영향을 받습니다. 추악하고 항상 문제가 되는 "경로 이름 확장"도 있습니다. 일반적으로 별로 유용하지 않습니다. 아니면 극도의 주의를 기울여 사용하세요.
답변2
보세요BinaryZebra의 답변자세한 설명을 위해. TLDP의 다음 인용문은 잘못된 것으로 알려져 있습니다.
원래:
보고 있다http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html:
"PARAMETER"의 첫 번째 문자가 느낌표인 경우 Bash는 "PARAMETER"의 나머지 부분으로 구성된 변수 값을 변수 이름으로 사용한 다음 변수를 확장하고 해당 값을 나머지 대체에 사용합니다. "PARAMETER" 자체의 값입니다. 이를 간접 확장이라고 합니다.
물론 여러분은 직접 매개변수 확장에 익숙합니다. 위나 아래처럼 가장 간단한 경우에도 항상 발생하기 때문입니다.
franky ~> echo $SHELL /bin/bash
다음은 간접 확장의 예입니다.
franky ~> echo ${!N*} NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
이는 echo 와 다릅니다
$N*
.
쉘에서 그 효과를 볼 수 있습니다.
예:
$ TEST=(test1 test2 test3)
$ echo ${!TEST*}
TEST
$ echo ${!TEST[@]}
0 1 2
$ echo ${TEST[@]}
test1 test2 test3
$ echo ${#TEST[@]}
4
${!TEST[@]}
${TEST[@]}
, 및 사용의 차이점에 유의하세요 ${#TEST[@]}
.