변수 값을 동적 변수 이름으로 사용하는 방법은 무엇입니까?

변수 값을 동적 변수 이름으로 사용하는 방법은 무엇입니까?

이 질문을 찾아봤는데 제대로 질문하는 방법을 모르거나 일반적인 질문이 아니네요...

PHP에서는 이는 (거의) 사소한 일입니다.

function getSite(string $prefix = 'prod') {
  $DEV_SITE='dev.site.com';
  $PROD_SITE='www.site.com';
  
  $site = strtoupper("{$prefix}_site");

  return ${$site};
}

getSite();      // www.site.com
getSite('dev'); // dev.site.com

차근차근 실천해 보도록 하겠습니다.

_SITE접미사가 붙은 변수 세트가 있습니다 .

DEV_SITE=dev.site.com
PROD_SITE=www.site.com

접두사만 매개변수로 사용하여 스크립트를 호출하고 싶습니다. 기본값은 PROD입니다.

#!/bin/bash

PREFIX=${1:-PROD}

echo $PREFIX
---

$ script.sh dev
dev
$ script.sh
PROD

내 변수 이름 중 하나를 얻기 "_SITE"위해 추가하고 싶습니다 .$PREFIX

VAR_NAME="${1:-PROD}_SITE"
echo $VAR_NAME
---

$ script.sh dev
dev_SITE
$script.sh
PROD_SITE

아 www, dev_SITE유효하지 않지만 발신자가 차이점을 알 필요는 없습니다.

dev따라서 변수 이름과 일치하도록 변환되도록 매개변수를 "대소문자를 구분하지 않음"으로 만들어 보겠습니다 .

SITE="${1:-PROD}_SITE"
# This does NOT work:
SITE="${1:-PROD^^}_SITE"
echo ${SITE^^}
---

$ script.sh dev
DEV_SITE
$script.sh
PROD_SITE

엄청난. 하지만 가장 쉽게 얻을 수 있는 방법은 무엇일까요?그 이름?

내가 시도한 모든 것에서 ${SITE^^}"잘못된 대체" 오류가 발생했습니다.

echo ${$SITE^^}_PROD
echo ${${!SITE^^}_PROD}
echo ${"${SITE^^}_PROD"}
echo ${"${!SITE^^}_PROD"}

등...

할당하고 재할당하면 작동합니다.

SITE="${1:-PROD}_SITE"
SITE=${!SITE^^}
echo $SITE
---

$ script.sh dev
dev.site.com
$ script.sh
prod.site.com

나는 이것이 한 단계에서 모든 대체 작업을 수행하는 것과 관련이 있다고 생각하지만 하위 쉘을 사용하고 이름을 다른 명령에 연결하려고 시도했지만 알아낼 수 없습니다.

답변1

당신은 그것을 사용할 수 있습니다 nameref.

현재 bash맨페이지에서:

선언 또는 로컬 내장 명령의 -n 옵션(아래 선언 및 로컬에 대한 설명 참조)을 사용하여 변수에 nameref 속성을 할당하여 nameref 또는 다른 변수에 대한 참조를 생성할 수 있습니다. 이를 통해 변수를 간접적으로 조작할 수 있습니다. nameref 변수가 참조, 할당, 설정 해제되거나 해당 속성이 수정될 때마다(nameref 속성 자체를 사용하거나 변경하는 경우 제외) 실제로 작업은 nameref 변수 값으로 지정된 변수에 대해 수행됩니다. nameref는 일반적으로 쉘 함수에서 이름이 함수에 인수로 전달되는 변수를 참조하는 데 사용됩니다. 예를 들어 변수 이름을 셸 함수의 첫 번째 인수로 전달하는 경우 다음을 실행합니다.

         declare -n ref=$1

첫 번째 매개변수로 전달된 변수 이름을 값으로 가지는 함수 내부에 nameref 변수 ref를 만듭니다. ref에 대한 참조 및 할당과 해당 속성에 대한 변경은 이름이 $1로 전달되는 변수에 대한 참조, 할당 및 속성 수정으로 처리됩니다. for 루프의 제어 변수에 nameref 속성이 있는 경우 단어 목록은 쉘 변수 목록이 될 수 있으며 루프가 실행될 때 목록의 각 단어에 대해 이름 참조가 설정됩니다. nameref 속성은 배열 변수에 할당될 수 없습니다. 그러나 nameref 변수는 배열 변수와 첨자 배열 변수를 참조할 수 있습니다. unset 내장 명령의 -n 옵션을 사용하여 Nameref를 설정 해제할 수 있습니다. 그렇지 않은 경우, nameref 변수의 이름을 인수로 하여 unset을 수행하면 nameref 변수가 참조하는 변수가 unset됩니다.

이것은 nameref를 사용하는 스크립트 버전입니다.

#!/bin/bash

set -u

PROD_SITE='prod.example.com'
DEV_SITE='dev.example.com'
PREFIX=${1:-PROD}
SITEVAR=${PREFIX^^}_SITE

declare -n SITE=$SITEVAR

printf "Site is '%s'.\n" "${SITE}"

답변2

_SITE 접미사가 붙은 변수 세트가 있습니다.

도울 수 있다면 하지 마세요. 가능하다면 연관 배열(기본 배열과 유사하지만 인덱스가 문자열임)을 사용하세요. 이것은 다음을 인쇄합니다 www.site.com:

declare -A sites=([dev]=dev.site.com [prod]=www.site.com)
site=prod
echo "${sites[$site]}"

답변3

앞서 살펴본 것처럼 Bash는 역참조 유틸리티("변수 이름과 동일한 값을 제공")를 제공하므로 이 작업이 상대적으로 간단합니다. 잘못된 선택을 확인하는 것은 범위를 벗어날 수 있지만 set -u존재하지 않는 변수를 사용하면 참조되는 경우 스크립트가 중단됩니다.

$ ./625908.sh dev
Prefix is 'DEV'.
Site is 'dev.example.com'.
$ ./625908.sh fake
Prefix is 'FAKE'.
./625908.sh: line 9: !SITEVAR: unbound variable

따라서 이 스크립트를 살펴보십시오.

#!/bin/bash
set -u
PROD_SITE='prod.example.com'
DEV_SITE='dev.example.com'
PREFIX=${1:-PROD}
PREFIX=${PREFIX^^} # Squash to uppercase
printf "Prefix is '%s'.\n" "${PREFIX}"
SITEVAR="${PREFIX}_SITE"
SITE="${!SITEVAR}"
printf "Site is '%s'.\n" "${SITE}"

이는 약간 단순화될 수 있지만 많이는 아닙니다.

#!/bin/bash
set -u
PROD_SITE='prod.example.com'
DEV_SITE='dev.example.com'
PREFIX=${1:-PROD}
SITEVAR=${PREFIX^^}_SITE
SITE="${!SITEVAR}"
printf "Site is '%s'.\n" "${SITE}"

관련 정보