간단한 질문입니다. Bash 쉘은 쉘 스크립트를 작성할 때 포인터 사용을 지원합니까?
${var[@]}
나는 배열을 반복할 때 스프레드 표기법에 익숙 $var
하지만 이것이 배열 인덱스를 반복하기 위해 포인터를 활용하고 있는지 잘 모르겠습니다. bash는 다른 언어와 마찬가지로 메모리 주소에 대한 액세스를 제공합니까?
Bash가 포인터 사용을 지원하지 않으면 다른 쉘은 무엇을 합니까?
답변1
포인터(위치를 가리키는메모리)은 Python이든 셸이든 C보다 높은 수준에서는 실제로 유용한 개념이 아닙니다. 객체에 대한 참조는 확실히 고급 언어에서 유용하며 복잡한 데이터 구조를 구축하는 데 필요할 수도 있습니다. 그러나 대부분의 경우 메모리 주소 측면에서 생각하는 것은 너무 낮은 수준이므로 많이 사용할 수 없습니다.
Bash(및 기타 쉘)에서는 notation을 사용하여 배열 요소의 값을 가져오고 ${array[index]}
, 를 사용하여 값을 할당 array[index]=...
하고, 를 사용하여 배열의 요소 수를 가져올 수 있습니다 ${#array[@]}
. 괄호 안의 표현식은 산술 표현식입니다. 가상의 예로 모든 배열 멤버에 상수 접두사를 추가할 수 있습니다.
for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
array[i]="foo-${array[i]}"
done
( 인덱스가 아닌 값에만 관심을 갖는다면 for x in "${array[@]}" ; do...
괜찮을 것입니다 .)
그리고연관또는 희소 배열, 숫자를 반복하는 것은 그다지 의미가 없지만 배열 키/인덱스를 가져오는 데는 사용해야 합니다 ${!array[@]}
. 예를 들어
declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do
echo "${assoc[$i]}"
done
게다가 Bash에는 다른 변수를 간접적으로 가리키는 두 가지 방법이 있습니다.
- 간접 확장, 사용
${!var}
문법, 값이 있는 변수의 값을 사용합니다.이름에 있고var
, - 이름 참조,사용 필요
declare
내장(또는ksh
-호환 동의어,typeset
).declare -n ref=var
참조ref
변수var
.
Namerefs는 또한 인덱싱을 지원합니다. 왜냐하면 사용이 배열로 사용되며 두 번째 요소로 명명된 변수를 참조하기 때문 입니다 arr=(a b c); declare -n ref=arr;
.${ref[1]}
b
${!p[1]}
p
Bash에서 namerefs는 문자 그대로 참조를 의미합니다.이름, 함수 내에서 nameref를 사용하면 지정된 변수의 로컬 값이 사용됩니다. 그러면 인쇄됩니다 local value of var
.
#!/bin/bash
fun() {
local var="local value of var"
echo "$ref";
}
var="global var"
declare -n ref=var
fun
Bash FAQ에는간접 참조에 대한 더 긴 기사, 또한.
답변2
아니요, bash
"포인터"는 없지만 참조가 있습니다.
$ spam="fred"
$ declare -n tripe=spam
$ echo $tripe
fred
$ tripe=juki
$ echo $spam
juki
bash
매뉴얼 페이지 에서 :
declare
내장 명령의 -n 옵션을 사용하여 nameref 속성을 변수에 할당하여local
nameref 또는 다른 변수에 대한 참조를 생성할 수 있습니다. 이를 통해 변수를 간접적으로 조작할 수 있습니다. nameref 변수가 참조, 할당, 설정 해제되거나 해당 속성이 수정될 때마다(nameref 속성 자체를 사용하거나 변경하는 경우 제외) nameref 변수의 값으로 지정된 변수에 대해 작업이 실제로 수행됩니다. nameref는 일반적으로 쉘 함수에서 이름이 함수에 인수로 전달되는 변수를 참조하는 데 사용됩니다. 예를 들어 변수 이름을 셸 함수의 첫 번째 인수로 전달하는 경우 다음을 실행합니다.declare -n ref=$1
함수 내에서 첫 번째 매개변수로 전달된 변수 이름을 값으로 갖는 nameref 변수 ref가 생성됩니다. ref에 대한 참조 및 할당과 해당 속성에 대한 변경은 이름이 $1로 전달되는 변수에 대한 참조, 할당 및 속성 수정으로 처리됩니다. for 루프의 제어 변수에 nameref 속성이 있는 경우 단어 목록은 쉘 변수 목록이 될 수 있으며 루프가 실행될 때 목록의 각 단어에 대해 이름 참조가 설정됩니다. nameref 속성은 배열 변수에 할당될 수 없습니다. 그러나 nameref 변수는 배열 변수와 첨자 배열 변수를 참조할 수 있습니다. 내장된 -n 옵션을 사용하여 Nameref를 설정 해제할 수 있습니다
unset
. 그렇지 않고unset
nameref 변수의 이름을 인수로 실행하면 nameref 변수가 참조하는 변수가 설정 해제됩니다.
답변3
아니요, 쉘은 "포인터"(C에서 이해되는 바와 같이)를 사용하지 않습니다.
배열은 인덱스를 사용할 수 있지만 echo "${array[2]}"
예제 @
의 배열은 실제로 "포인터"가 아닙니다. "값의 배열 목록"을 표현하는 방법입니다. 쉘 파서가 이해할 수 있는 것. 다음과 유사:
$ echo "$@"
모든 위치 매개변수 리스트로 확장합니다.
답변4
bash 정수 인덱스 배열은 다음과 같이 반복적으로 정의하고 액세스할 수 있습니다.
declare -a obj
obj+=("val1")
obj+=("val2")
for item in ${obj[@]}; do
echo "${obj[${item}]} ${item}"
done
Bash의 연관 또는 문자열 기반 인덱스 배열에는 다음 반복 정의가 필요합니다.
declare -A obj
obj["key1"]="val1"
obj["key2"]="val2"
for item in ${!obj[@]}; do
echo "${obj[${item}]} ${item}"
done
bash에서 포인터 및 포인터 사용에 대한 질문에 대답하려면 컴파일된 bash 바이너리의 내부 함수는 스택에 할당된 메모리에 대한 포인터를 사용하고 실제로는 eval
.http://tldp.org/LDP/abs/html/ivr.html)
용이 있으므로 eval
안전상의 위험이 있으므로 주의해서 사용해야 합니다.