변수 이름이 문자열로 저장된 경우 변수 값을 얻는 방법은 무엇입니까?


142

변수 이름이 문자열 인 경우 bash 변수 값을 어떻게 검색 할 수 있습니까?

var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.

문맥:

AMI ( Amazon Machine Image )가 있고 각 AMI의 인스턴스를 몇 개씩 실행하려고합니다. 부팅이 완료되면 AMI 유형에 따라 각 인스턴스를 설정하려고합니다. AMI 내부에서 많은 스크립트 또는 비밀 키를 굽고 싶지 않기 때문에 일반화 된 시작 스크립트를 준비 하고 공개적으로 액세스 할 수있는 링크로 S3에 넣었습니다 . rc.local에서는 시작 스크립트를 가져 와서 실행하는 작은 코드 조각을 넣었습니다. 이것이 AMI에있는 모든 것입니다. 그런 다음 각 AMI는 모든 AMI 및 각각에 대한 특수 설정 스크립트에 적용 가능한 공통 구성 스크립트에 액세스합니다. 이 스크립트는 비공개이며 액세스하려면 서명 된 URL이 필요합니다.

이제 AMI 인스턴스 (my_private_ami_1)를 시작하면 S3에 표시되는 하나 이상의 파일에 대해 서명 된 URL을 전달합니다.이 파일에는 모든 개인 스크립트에 대한 서명 된 URL이 키 / 값 쌍으로 포함되어 있습니다.

config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...
시작 스크립트가 실행되면 위의 파일을 다운로드하여 파일을 다운로드 source합니다. 그런 다음 AMI 유형을 확인하고 올바른 설정 스크립트를 선택합니다.

ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises

이제 AMI 유형에 관계없이 인스턴스를 시작하고 인스턴스를 스스로 관리 할 수있는 일반 코드를 사용할 수 있습니다.

답변:


257

당신은 사용할 수 있습니다 ${!a}:

var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'

다음은 간접 파라미터 확장 의 예입니다 .

매개 변수 확장의 기본 형식은입니다 ${parameter}. 값 parameter이 대체됩니다.

의 첫 번째 문자 parameter가 느낌표 (!)이면 가변 간접 수준이 도입됩니다. Bash는 나머지 parameter이름으로 작성된 변수 값을 변수 이름으로 사용합니다. 그런 다음이 변수가 확장되고 해당 값이 parameter자체 값 대신 나머지 대체에 사용 됩니다.


4
이것은 OSX bash에서 나를 위해 작동하지만 데비안에서는 그렇지 않습니까? 데비안에서는 Bad substitution오류가 발생합니다.
23inhouse

11
@ 23inhouse 다음을 사용하여 스크립트를 실행하고 /bin/sh있습니까? 그렇다면 /bin/bash대신 사용하십시오. Debian Squeeze부터는 대신에 심볼릭 링크/bin/sh 로 변경되었습니다 . 이 특정 구문을 지원하지 않으며 오류 를 출력합니다 . dashbashdashBad substitution
Phil Ross

8
배열에 속하는 변수 이름에 대해이 작업을 수행하는 방법이 있습니까?
Loupax

bash와 우분투 작업
Sergey P. 일명 azure

1
@DoronShai이의 강타 참조 설명서에 설명 간접적 인 매개 변수 확장의 예입니다 gnu.org/software/bash/manual/html_node/...
필 로스

29
X=foo
Y=X
eval "Z=\$$Y"

Z를 "foo"로 설정

eval 값을 통해 실수로 코드를 추출 할 수 있으므로 주의해서 사용 하십시오${Y} . 코드 삽입으로 인해 피해를 입을 수 있습니다.

예를 들어

Y="\`touch /tmp/eval-is-evil\`"

만들 것 /tmp/eval-is-evil입니다. 물론 이것은 일부일 수도 있습니다 rm -rf /.


내 꼬리를 구했습니다. ty
raffian

9

검색 키워드를 수정하고 알았습니다 :).

eval a=\$$a
시간 내 줘서 고마워.


의 값을 통해 실수로 코드를 추출 할 수 있으므로 eval을 사용하여주의하십시오 ${Y}. 사용자 "anon"의 답변으로 추가 한 내용을 참조하십시오.
try-catch-finally

이것은 유일한 작동 답변입니다. 아이러니하다.
Ctrl S

8

동료 zsh 사용자의 경우 허용되는 답변과 동일한 것을 수행하는 방법은 다음을 사용하는 것입니다.

${(P)a}

이를 매개 변수 이름 교체 라고합니다.

그러면 매개 변수 이름의 값이 추가 매개 변수 이름으로 해석되어 해당 위치에서 적절한 값이 사용됩니다. typeset 명령 계열 중 하나 (특히 경우 변환)로 설정된 플래그는이 방식으로 사용 된 name 값에 적용되지 않습니다.

중첩 된 매개 변수 또는 명령 대체와 함께 사용되는 경우 결과는 동일한 방식으로 매개 변수 이름으로 사용됩니다. 예를 들어, 'foo = bar'및 'bar = baz'인 경우 문자열 $ {(P) foo}, $ {(P) $ {foo}} 및 $ {(P) $ (echo bar) }는 'baz'로 확장됩니다.

마찬가지로 참조 자체가 중첩 된 경우 플래그가있는 표현식은 마치 매개 변수 이름으로 직접 대체 된 것처럼 처리됩니다. 이 중첩 된 대체가 둘 이상의 단어로 배열을 생성하면 오류입니다. 예를 들어, 매개 변수 assoc이 연관 배열 인 'name = assoc'인 경우 '$ {$ {(P) name} [elt]}'은 연관 첨자 'elt'의 요소를 나타냅니다.


0

현대 쉘은 이미 배열 (및 연관 배열)을 지원합니다. 따라서 사용하고 평가를 줄이십시오.

var1="this is the real value"
array=("$var1")
# or array[0]="$var1"

그런 다음 호출 할 때 $ {array [0]}


커맨드 라인 인수에서 문자열을 얻는 경우 (예 :)이 작동 $1합니까?
jena

0

답변을 기반으로 : https://unix.stackexchange.com/a/111627

###############################################################################
# Summary: Returns the value of a variable given it's name as a string.
# Required Positional Argument: 
#   variable_name - The name of the variable to return the value of
# Returns: The value if variable exists; otherwise, empty string ("").
###############################################################################
get_value_of()
{
    variable_name=$1
    variable_value=""
    if set | grep -q "^$variable_name="; then
        eval variable_value="\$$variable_name"
    fi
    echo "$variable_value"
}

test=123
get_value_of test
# 123
test="\$(echo \"something nasty\")"
get_value_of test
# $(echo "something nasty")

0

배열과 동일한 문제가 있었지만 배열을 조작하는 경우 수행하는 방법은 다음과 같습니다.

array_name="ARRAY_NAME"
ARRAY_NAME=("Val0" "Val1" "Val2")

ARRAY=$array_name[@]
echo "ARRAY=${ARRAY}"
ARRAY=("${!ARRAY}")
echo "ARRAY=${ARRAY[@]}"
echo "ARRAY[0]=${ARRAY[0]}"
echo "ARRAY[1]=${ARRAY[1]}"
echo "ARRAY[2]=${ARRAY[2]}"

출력됩니다 :

ARRAY=ARRAY_NAME[@]
ARRAY=Val0 Val1 Val2
ARRAY[0]=Val0
ARRAY[1]=Val1
ARRAY[2]=Val2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.