[Bash] $ {} 자리 표시자를 텍스트 파일로 바꾸는 방법은 무엇입니까?


Answers

Sed !

주어진 template.txt :

The number is ${i}
The word is ${word}

우리는 단지 말해야 만합니다 :

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

팁에 대한 Jonathan Leffler 덕분에 여러 개의 -e 인수를 동일한 sed 호출에 전달했습니다.

Question

"template"파일의 출력을 ${dbName} 과 같은 변수가있는 MySQL에 파이프하고 싶습니다. 이 인스턴스를 대체하고 출력을 표준 출력으로 덤프하는 명령 줄 유틸리티는 무엇입니까?




같은 것을 궁금해하면서이 스레드를 발견했습니다. 그것은 저에게 영감을주었습니다 (backticks에주의하십시오)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world



당신이 Perl 을 사용하고 있다면, 그것은 제 제안 일 것입니다. 아마도이 일을 훨씬 쉽게하는 방법을 알고있는 아마 sed 및 / 또는 AWK 전문가가있을지라도. 당신이 대체물을위한 dbName 이상으로 더 복잡한 매핑을 가지고 있다면 이것을 쉽게 확장 할 수 있습니다. 그러나 그 점을 표준 Perl 스크립트에 넣을 수도 있습니다.

perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql

약간 더 복잡한 작업을 수행하는 짧은 Perl 스크립트 (여러 개의 키 처리) :

#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;

위의 스크립트의 이름을 replace-script로 지정하면 다음과 같이 사용할 수 있습니다.

replace-script < yourfile | mysql



file.tpl :

The following bash function should only replace ${var1} syntax and ignore 
other shell special chars such as `backticks` or $var2 or "double quotes". 
If I have missed anything - let me know.

script.sh :

template(){
    # usage: template file.tpl
    while read -r line ; do
            line=${line//\"/\\\"}
            line=${line//\`/\\\`}
            line=${line//\$/\\\$}
            line=${line//\\\${/\${}
            eval "echo \"$line\""; 
    done < ${1}
}

var1="*replaced*"
var2="*not replaced*"

template file.tpl > result.txt



/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



구성 파일 형식을 제어 할 수 있으면 bash 자체에서 수행 할 수 있습니다. 당신은 단지 서브 쉘 대신에 설정 파일을 소스 화 ( ".")해야합니다. 이렇게하면 하위 쉘 (하위 쉘이 종료 될 때 변수가 사라지는) 대신 현재 쉘의 컨텍스트에서 변수가 작성되고 계속 존재하게됩니다.

$ cat config.data
    export parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA
    export parm_user=pax
    export parm_pwd=never_you_mind

$ cat go.bash
    . config.data
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

설정 파일이 쉘 스크립트가 될 수 없다면, 이렇게하기 전에 컴파일 만하면됩니다 (컴파일은 입력 형식에 달려 있습니다).

$ cat config.data
    parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA # JDBC URL
    parm_user=pax                              # user name
    parm_pwd=never_you_mind                    # password

$ cat go.bash
    cat config.data
        | sed 's/#.*$//'
        | sed 's/[ \t]*$//'
        | sed 's/^[ \t]*//'
        | grep -v '^$'
        | sed 's/^/export '
        >config.data-compiled
    . config.data-compiled
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

특정 경우에는 다음과 같이 사용할 수 있습니다.

$ cat config.data
    export p_p1=val1
    export p_p2=val2
$ cat go.bash
    . ./config.data
    echo "select * from dbtable where p1 = '$p_p1' and p2 like '$p_p2%' order by p1"
$ bash go.bash
    select * from dbtable where p1 = 'val1' and p2 like 'val2%' order by p1

그런 다음 go.bash의 출력을 MySQL과 voila로 파이프하십시오. 데이터베이스를 파괴하지 않길 바랍니다 .-).




Sigil 과 같은 것을 사용하는 것이 좋습니다 : https://github.com/gliderlabs/sigil

그것은 하나의 바이너리로 컴파일되므로 시스템에 설치하는 것이 매우 쉽습니다.

그런 다음 다음과 같은 간단한 한 줄 짜기를 할 수 있습니다.

cat my-file.conf.template | sigil -p $(env) > my-file.conf

이것은 eval 보다 훨씬 안전하고 regex 나 sed 를 사용하는 것이 더 쉽습니다.




선택의 여지가 많지만, 나는 힙에 내 것을 던질 것이라고 생각했습니다. Perl 기반이며 $ {...} 형식의 변수 만 대상으로하며 인수로 처리 할 파일을 가져 와서 변환 된 파일을 stdout에 출력합니다.

use Env;
Env::import();

while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }

print "$text";

물론 나는 정말로 perl 사람이 아니기 때문에 쉽게 치명적인 결함이 될 수있다.




eval 사용 함에도 불구하고 사용하기에 안전해야하는 강력한 Bash 함수 가 있습니다.

입력 텍스트의 모든 ${varName} 변수 참조는 호출 쉘의 변수에 따라 확장됩니다.

{...} $varName {...} 와 같은 명령 치환 ( $(...) 과 레거시 구문 `...` )이나 산술 치환 (( $varName 과 같은) $((...)) 및 기존 구문 $[...] ).

$ 를 리터럴로 취급하려면 \ -escape it; 예 : \${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



최신 정보

다음은 $ VAR 또는 $ {VAR}과 같은 변수를 대체하는 간단한 질문에 대한 yottatsa 의 해결책이며 간단한 한 줄짜리 코드입니다

i=32 word=foo envsubst < template.txt

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

envsubst < template.txt

내 맥에서는 gettextMacGPG2의 일부로 설치 한 것처럼 보입니다.

이전 답변

다음은 비슷한 질문에 대한 mogsie 의 솔루션 개선입니다. 내 솔루션에서는 큰 따옴표를 사용하지 않아도되지만, mogsie의 것은 그렇습니다.하지만 그의 코드는 하나의 라이너입니다!

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

이 두 솔루션의 장점은 정상적으로 $ ((...)),`...`및 $ (...)가 발생하지 않는 몇 가지 유형의 쉘 확장 만 얻을 수 있다는 점입니다. 단 백 슬래시 여기서 이스케이프 문자를 사용하지만 구문 분석에 버그가 있다는 것에 대해 걱정할 필요가 없으며 여러 줄을 올바르게 처리 할 수 ​​있습니다.




나는 최근에 관심이 있었기 때문에 이것에 대해서 다시 생각해 보았습니다. 원래 생각한 도구는 autotools의 매크로 프로세서 인 m4 였습니다. 따라서 원래 지정한 변수 대신 다음을 사용하십시오.

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



여기에 전 답변을 기반으로 펄과 내 솔루션, 환경 변수를 바꿉니다 :

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile



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