이전에 선언된 변수의 변수 바꾸기

이전에 선언된 변수의 변수 바꾸기

이는 VAR2에 따라 업데이트되어야 하는 템플릿 변수 VAR1입니다. 변수의 순서는 다음과 같습니다. sed 명령 없이 VAR1을 업데이트하는 방법은 무엇입니까?

#!/bin/bash
VAR1="<tr>
    <th>\$VAR2</th>
  </tr>"
VAR2=test
echo $VAR2

답변1

당신이 사용할 수있는 envsubst:

(포함된 POSIX 쉘을 사용하십시오 bash):

VAR1="<tr>
    <th>\$VAR2</th>
  </tr>"
VAR2=test

expanded_VAR1=$(
  export VAR2
  printf '%s\n' "$VAR1" |
    envsubst '$VAR2'
)

또는 모든 단어 확장(매개변수 확장, 명령 대체, 산술 확장)을 수행합니다.~ 위에zsh매개변수 확장의 경우 해당 e매개변수 확장 플래그를 사용할 수 있습니다 .

#!/bin/zsh -
VAR1="<tr>
    <th>\$VAR2</th>
  </tr>"
VAR2=test

expanded_VAR1=${(e)VAR1}

POSIX 셸에서는 eval및 here-document를 사용하여 유사한 작업을 수행할 수 있습니다.

VAR1="<tr>
    <th>\$VAR2</th>
  </tr>"
VAR2=test

expanded_VAR1=$(eval "cat << EOF
$VAR1
EOF")

bash또는에 대한 또 다른 옵션은 다음을 zsh사용하는 것입니다 printf.

VAR1='<tr>
    <th>%s</th>
  </tr>'
VAR2=test

printf -v expanded_VAR1 -- "$VAR1" "$VAR2"

zsh(사용하지 않음 )을 사용하면 다음 구문을 사용하여 th 매개변수를 참조 bash할 수 있습니다 %n$s(많은 구현에서와 마찬가지로 ) .printf(3)n

#! /bin/zsh -
VAR1='<tr>
    <th>%1$s</th> <th>%1$s again</th> <th>%2$s</th>
  </tr>'
VAR2=test VAR3=test2

printf -v expanded_VAR1 -- "$VAR1" "$VAR2" "$VAR3"

또는 명명된 형식 지시문을 사용합니다( zformat, , NUL 및 10진수를 제외한 단일 바이트 문자로 제한됨).-.

#! /bin/zsh -
VAR1='<tr>
    <th>%a</th> <th>%a again</th> <th>%b</th>
  </tr>'
VAR2=test VAR3=test2

zformat -f expanded_VAR1 "$VAR1" "a:$VAR2" "b:$VAR3"

를 사용하면 대신 를 사용하여 HTML의 특수 문자(예: be )를 올바르게 인코딩 ksh93할 수 있지만 ASCII가 아닌 문자의 경우 iso8859-1 문자 집합을 사용하는 로케일에서만 올바르게 작동합니다. 지원되지 않지만 작동합니다 .%H%sprintf&&amp;ksh93printf-vexpanded_VAR1=${ printf... ;}

/ 메소드를 사용하면 printf템플릿의 리터럴 문자를 zformat이스케이프할 수 있고(다음과 같이) / +here-doc 메소드를 사용하면 / / 접두사를 붙여 이스케이프할 수 있습니다. 그러면 AFAIK, 탈출구가 없습니다.%%%\\\printfeeval$`\\envsubst$

답변2

매개변수 확장을 사용하여 var1의 고유 문자열을 var2의 값으로 바꿀 수 있습니다.

var1='<tr>
    <th>unique_placeholder_var2</th>
  </tr>'
var2=test
echo "${var1/unique_placeholder_var2/"$var2"}"

답변3

var1올바른 형식의 XML이 포함되어 있다고 가정합니다 .

var1='
<tr>
  <th>$var2</th>
</tr>
'

var2=test

xmlstarlet그런 다음 모든 노드의 값을 th다음과 같이 쉘 변수의 값으로 리터럴 값으로 바꿀 수 있습니다 .$var2var2

var1=$( printf '%s\n' "$var1" | xmlstarlet ed -u '//th[text() = "$var2"]' -v "$var2" )

이는 수정하려는 모든 노드를 xmlstarlet선택하기 위해 XPATH 쿼리를 호출합니다 . 이 노드의 값은 쉘 변수의 값으로 대체되고 결과는 표준 출력에 기록됩니다.thxmlstarletvar2

$ printf '%s\n' "$var1"
<?xml version="1.0"?>
<tr>
  <th>test</th>
</tr>

이는 var2XML 문서에 포함할 값을 올바르게 인코딩합니다.

$ var1='
<tr>
  <th>$var2</th>
</tr>
'
$ var2='HÉLLO :->'
$ var1=$( printf '%s\n' "$var1" | xmlstarlet ed -u '//th[text() = "$var2"]' -v "$var2" )
$ printf '%s\n' "$var1"
<?xml version="1.0"?>
<tr>
  <th>H&#xC9;LLO :-&gt;</th>
</tr>

답변4

템플릿에서 변수를 바꾸는 일반적인 방법:

  • bash 정규식을 사용하여 변수 이름을 캡처합니다(탐욕적 일치로 인해 여기에서는 변수 이름이 오른쪽에서 왼쪽으로 일치됩니다).
  • 변수를 사용하여 간접적으로 변수 값 얻기
  • 무한 루프를 방지하려면 입력 문자열에서 일치하는 varname을 제거하세요(이렇게 하면 원래 문자열이 손상되므로 추가로 필요한 경우 백업하세요).

데모

  1. 대체할 템플릿과 (전부는 아님) 변수를 설정합니다.

    VAR1="<tr>
        <th>\$VAR2</th>
        <th>\$VAR3</th>
      </tr>"
    VAR2=test
    unset VAR3
    
  2. 교체 수행

    result=""
    while [[ $VAR1 =~ (.*)\$([[:alpha:]_][[:alnum:]_]*)(.*) ]]; do
        varname=${BASH_REMATCH[2]}
        [[ -v $varname ]] && replacement=${!varname} || replacement="\$${varname}"
        result="${replacement}${BASH_REMATCH[3]}${result}"
        VAR1=${BASH_REMATCH[1]}
    done
    result="${VAR1}${result}"
    declare -p result
    
  3. 검사 결과

    declare -- result="<tr>
        <th>test</th>
        <th>\$VAR3</th>
    </tr>"
    

이를 위해서는 -v운영자가 bash 버전 4.3+을 사용해야 합니다.

관련 정보