쉘 스크립트로 변수 내용의 내용을 인쇄 할 수 있습니까? (간접 참조)


13

다음 변수를 선언했다고 가정 해 봅시다.

$ var='$test'
$ test="my string"

내용을 인쇄하면 다음이 표시됩니다.

$ echo $var
$test

$ echo $test
my string

나는의 내용의 내용을 인쇄하는 방법을 찾으려면 $var(내용입니다 $test). 그래서 나는 다음을 시도했다.

$ echo $(echo $var)
$test

그러나 결과는 다음 $test과 같습니다 "my string"... bash를 사용하여 변수 내용의 내용을 인쇄 할 수 있습니까?


당신은 할 수 편집 사용중인 쉘을하는, 또는 당신이 가지고있는 이동성 요구 사항을 말할 게시물을?
Michael Homer

@MichaelHomer 물론,이 정보를 정확히 어떻게 확인할 수 있습니까?
라파엘 무이 나르 스크

그것은 당신이 선택하는 것보다 더 많은 것입니다. 예를 들어,, ash또는 bash, 또는 csh, 또는 dash, ... 또는 zsh, POSIX로 스크립트를 실행 중 sh입니까? 아니면 다른 시스템에서 작업해야합니까?
Michael Homer

@MichaelHomer 아, 알겠습니다 ... 나는 bash를 사용하고 있습니다. 마지막 질문을 변경하고 새 태그를 삽입하겠습니다.
라파엘 무이 나르 스크

답변:


21

bash의 간접 변수 확장을 사용 하여이 작업을 수행 할 수 있습니다 ( $참조 변수를 생략해도 괜찮다면 ).

$ var=test
$ test="my string"
$ echo "$var"
test
$ echo "${!var}"
my string

3.5.3 쉘 매개 변수 확장


10

포함 된 변수 이름 var앞에 접두사가 $있는 경우 다음을 사용할 수 있습니다 eval.

$ var='$test'
$ test="my string"
$ eval echo $var
my string

여기서 일어나는 일 :

  • bash $var는 값으로 확장 되어 명령을 $test생성합니다 eval echo $test.
  • evalecho $test표현을 평가 하고 원하는 결과를 생성합니다.

eval일반적으로 사용 하는 것은 위험 할 수 있습니다 (에 저장된 내용에 따라 다름 var). 피하는 것이 좋습니다. 간접 확장 기능은 귀하의 경우에 더 낫습니다 (그러나 $로그인을 제거해야합니다 $test).


물론, 이것은 잘못된 유형입니다. 원래 게시물에는 작은 따옴표가 있습니다. 결정된.
Danila Kiver 2018 년

4
예기치 않은 단어 분리 및 와일드 카드 확장으로 인한 문제를 피하기 위해 항상 큰 따옴표로 묶은 변수 참조를 권장합니다. 을 사용하면 eval두 줄의 큰 따옴표가 필요합니다 eval echo "\"$var\"". 이것은 eval당신이 언급 한 다른 사용의 위험에 대해서는 아무 것도하지 않습니다 .
Gordon Davisson

9

Jesse_b의 답변 과 유사 하지만 변수 간접 지정 대신 이름 참조 변수를 사용합니다 ( bash4.3 이상 필요 ).

$ declare -n var=test
$ test="my string"
$ echo "$var"
my string

이름 참조 변수 var는 참조하는 변수 의 이름을 보유합니다. 변수가 다음과 같이 역 참조 될 때$var 의 값이 반환됩니다.

bash 이름 참조를 재귀 적으로 확인합니다.

$ declare -n var1=var2
$ declare -n var2=test
$ test="hello world"
$ echo "$var1"
hello world

완벽 성 bash을 기하기 위해 요구 사항에 따라 연관 배열 ( 4.0+)을 사용하는 것도이를 해결하는 한 가지 방법입니다.

$ declare -A strings
$ strings[test]="my string"
$ var=test
$ echo "${strings[$var]}"
my string

이를 통해 동적으로 결정될 수있는 키 또는 이름으로 둘 이상의 값에 액세스하는보다 유연한 방법을 제공합니다. 단일 범주에서 특정 범주의 모든 값을 수집하되 오염되지 않기 때문에 일부 키 (예 : ID로 액세스 할 수있는 이름 또는 목적으로 액세스 할 수있는 경로 이름)로 여전히 액세스 할 수있는 경우이 방법이 바람직 할 수 있습니다. 스크립트의 변수 네임 스페이스


3

zsh:

$ var='$test'
$ test='*'
$ printf '%s\n' ${(e)var}
*

Bourne과 같은 쉘

$ eval 'printf "%s\n" "'"$var"'"'
*

이러한 쉘에서 split + glob ( zsh예외) 를 방지하기 위해 변수 확장을 인용해야하며 echo임의의 데이터에는 사용할 수 없습니다.

모두 이후 (e)eval쉘 코드 평가가, 그것의 내용을 중요 $var임의의 명령 주입 취약점 (와 동일 할 수 그렇지 않으면 같은 컨트롤 내에서 숙박 ${!var}접근).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.