[bash] 텍스트 파일에서 $ {} 자리 표시자를 바꾸는 방법?

“템플릿”파일의 출력을 MySQL로 파이프하고 싶습니다 ${dbName}. 이 파일에는 산재 된 것과 같은 변수가 있습니다. 이러한 인스턴스를 바꾸고 출력을 표준 출력으로 덤프하는 명령 줄 유틸리티는 무엇입니까?



답변

세드 !

주어진 template.txt :

숫자는 $ {i}입니다
단어는 $ {word}입니다

우리는 다음과 같이 말해야합니다.

sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt

-e이 동일한 sed호출에 여러 인수를 전달하는 Jonathan Leffler에게 감사합니다 .


답변

최신 정보

다음은 $ VAR 또는 $ {VAR}과 같은 변수를 대체하는 간단한 질문에 대한 yottatsa 의 솔루션 이며 간단한 한 줄짜리입니다.

i=32 word=foo envsubst < template.txt

물론 i단어 가 당신의 환경에 있다면, 그것은 단지

envsubst < template.txt

내 Mac에서는 gettext의 일부로 MacGPG2 에서 설치된 것처럼 보입니다.

기존 답변

비슷한 질문에 대한 mogsie 솔루션의 개선 사항은 다음과 같습니다 . 내 솔루션에는 큰 따옴표를 escale 할 필요가 없으며 mogsie는하지만 하나는 라이너입니다!

eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null

이 두 가지 솔루션의 장점은 일반적으로 $ ((…)),`…`및 $ (…)가 아닌 몇 가지 유형의 셸 확장 만 얻을 수 있다는 것 입니다 . 여기서 문자를 이스케이프 처리하지만 구문 분석에 버그가 있다는 것을 걱정할 필요는 없으며 여러 줄을 올바르게 수행합니다.


답변

사용하십시오 /bin/sh. 변수를 설정하는 작은 쉘 스크립트를 작성한 다음 쉘 자체를 사용하여 템플리트를 구문 분석하십시오. 이와 같이 (개행을 올바르게 처리하도록 편집) :

파일 template.txt :

the number is ${i}
the word is ${word}

파일 script.sh :

#!/bin/sh

#Set variables
i=1
word="dog"

#Read in template one line at the time, and replace variables (more
#natural (and efficient) way, thanks to Jonathan Leffler).
while read line
do
    eval echo "$line"
done < "./template.txt"

산출:

#sh script.sh
the number is 1
the word is dog


답변

최근 관심사를 감안할 때 이것에 대해 다시 생각하고 있었고 원래 생각했던 도구는 m4autotools의 매크로 프로세서 라고 생각 합니다. 따라서 원래 지정한 변수 대신 다음을 사용합니다.

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"


답변

template.txt

Variable 1 value: ${var1}
Variable 2 value: ${var2}

data.sh

#!/usr/bin/env bash
declare var1="value 1"
declare var2="value 2"

parser.sh

#!/usr/bin/env bash

# args
declare file_data=$1
declare file_input=$2
declare file_output=$3

source $file_data
eval "echo \"$(< $file_input)\"" > $file_output

./parser.sh data.sh template.txt parsed_file.txt

parsed_file.txt

Variable 1 value: value 1
Variable 2 value: value 2


답변

여기의 강력한 배쉬 기능을 사용하면에도 불구하고 – 있음 eval– 안전해야 사용이.

${varName}입력 텍스트의 모든 변수 참조는 호출 쉘의 변수를 기반으로 확장됩니다.

다른 건 확장되지 않습니다 : 어느 변수 이름이되는 참조 하지 묶인 {...}(예 $varName)도 명령 대체 ( $(...)레거시 구문 `...`)이나 산술 대체 ( $((...))레거시 구문 $[...]).

$리터럴로 취급하려면 \이스케이프 처리하십시오. 예 :\${HOME}

입력은 stdin을 통해서만 허용됩니다 .

예:

$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)

기능 소스 코드 :

expandVarsStrict(){
  local line lineEscaped
  while IFS= read -r line || [[ -n $line ]]; do  # the `||` clause ensures that the last line is read even if it doesn't end with \n
    # Escape ALL chars. that could trigger an expansion..
    IFS= read -r -d '' lineEscaped < <(printf %s "$line" | tr '`([$' '\1\2\3\4')
    # ... then selectively reenable ${ references
    lineEscaped=${lineEscaped//$'\4'{/\${}
    # Finally, escape embedded double quotes to preserve them.
    lineEscaped=${lineEscaped//\"/\\\"}
    eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
  done
}

함수에는없는 것으로 가정 0x1, 0x2, 0x30x4그 때문에 문자 제어 문자 입력에 존재한다. 함수는 텍스트를 처리하기 때문에 내부적으로 사용되므로 안전한 가정이어야합니다.


답변

작성 rendertemplate.sh:

#!/usr/bin/env bash

eval "echo \"$(cat $1)\""

그리고 template.tmpl:

Hello, ${WORLD}
Goodbye, ${CHEESE}

템플릿을 렌더링합니다 :

$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl
Hello, Foo
Goodbye, Bar