연결된 변수 이름 역 참조


12

나는 이것을 할 수 있지만 변수의 문자열을 만든 다음 참조 해제해야합니다. 더 간단한 진술로 단축 할 수있는 방법이 있습니까?

#!/bin/bash

FRUITS="BANANA APPLE ORANGE"

BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS ); do
    fruit_colour="${fruit}_COLOUR"
    echo $fruit is ${!fruit_colour}
done

나는 ${!"${fruit}_COLOUR"}또는 \$${fruit}_COLOUR많은 다른 변형 을 시도했지만 효과가있는 유일한 방법은 문자열을 사용하는 것입니다.


!구문은 기본적으로 "두 번 대체"라는 변수 치환에 플래그입니다. 내부의 내용 ${…}이 변수 이름이어야 한다는 요구 사항은 변경하지 않습니다 . 따라서 다른 방법 ( eval) 을 사용하지 않으면 이름이 포함 된 변수를 사용하지 않아도 됩니다.
Gilles 'SO- 악마 그만두 다'

연관 배열을 사용하여 훨씬 더 명확하게 수행 할 수도 있습니다. 그러나 귀하의 질문에 대한 직접적인 답변이 아니므로 의견으로 추가하십시오.
패트릭

답변:


11

먼저 $(echo $FRUITS), for진술 에 사용할 필요가 없습니다 . 그냥 사용하면 $FRUITS충분합니다. 그런 다음을 사용하여 루프 내부의 선 중 하나를 제거 할 수 있습니다 eval.

이것은 eval단순히 bash에게 다음 진술에 대한 두 번째 평가 를하도록 지시 합니다 (즉, 일반 평가보다 하나 더). 은 \$같은 제 생존 평가 $하고, 다음의 평가는 이러한 처리를 $"노랑"등을 할 리졸 변수 이름의 개시로서

이렇게하면 중간 문자열을 만드는 별도의 단계가 필요하지 않습니다 (귀하의 질문의 주요 의도라고 생각합니다).

for fruit in $FRUITS ;do
    eval echo $fruit is \$${fruit}_COLOUR
done

패트릭 이 주석에서 언급 한 것처럼 대체 방법 의 경우 요소의 인덱스가 정수일 필요가없는 연관 배열을 대신 사용할 수 있습니다 . 과일 유형의 이름과 같은 문자열을 사용할 수 있습니다. 다음은 bash의 연관 배열을 사용하는 예입니다.

# This declares an associative array (It unsets it if it already exists)
declare -A colour
colour['BANANA']="Yellow"
colour["APPLE"]="Green or Red"
colour[MARTIAN ORANGE]="Blue"

for fruit in BANANA APPLE "MARTIAN ORANGE" ;do 
    echo "$fruit" is "${colour[$fruit]}"
done

6

bash-builtin eval을 사용하여 다음 을 수행 할 수 있습니다.

#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS );
do
    fruit_colour=${fruit}_COLOUR
    eval echo $fruit is \$${fruit_colour}
done

백 슬래시 달러 기호를 유의하십시오. 기본적으로 "eval"줄은 and bash 을 대체 $fruit하고 ${fruit_color}를 사용 eval하여을 호출하기 전에 두 번째 substition을 수행합니다 echo.


1

eval 문이 필요하지 않습니다. eval대부분의 언어에서 잘못된 일을하고 있다는 힌트입니다.

foo_var=10
bar_var=12

# Build a string with your var name of choice
chosen_prefix='foo'
var_name="${chosen_prefix}_var"

# Use bang to deference it
chossen_value=${!var_name}
echo "Chossen value: ${chossen_value}"

나는 eval적어도 사람들이 위험하다는 것을 알고, ( 공격자 통제하에있는 경우 명령 주입 취약점) ${!var}위험에 대해 알고 있고 그것을 아는 사람들이 적기 때문에 사용하는 것이 더 안전하다고 주장 한다. 시도하십시오 . 여기서 가장 좋은 방법은 연관 배열입니다. bash$chosen_prefixvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.