문제

"템플릿"파일의 출력을 MySQL로 파이프하고 싶습니다. ${dbName} 산재합니다. 이러한 인스턴스를 교체하고 출력을 표준 출력에 덤프하기위한 명령 줄 유틸리티는 무엇입니까?

도움이 되었습니까?

해결책

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 기도.

다른 팁

업데이트

다음은 해결책입니다 요타사 $ var 또는 $ {var}와 같은 변수를 대체하는 유사한 질문에서, 짧은 1 라이너입니다.

i=32 word=foo envsubst < template.txt

당연하지 만약 그리고 단어 당신의 환경에 있으면 그것은 단지입니다

envsubst < template.txt

내 Mac에서는 그것이의 일부로 설치된 것 같습니다. getText 그리고 MACGPG2

오래된 대답

다음은 솔루션의 개선입니다 mogsie 비슷한 질문에서, 내 솔루션은 당신이 이중 인용문을 제정 할 필요는 없다.

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

이 두 솔루션의 전원은 Backslash에서 일반적으로 $ ((...)),`및 $ (...)가 발생하지 않는 몇 가지 유형의 쉘 확장 만 얻는 것입니다. ~이다 여기에서 탈출 캐릭터이지만 구문 분석에 버그가 있다고 걱정할 필요는 없으며 여러 줄은 잘 작동합니다.

사용 /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

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

$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

다음은 이전 답변을 기반으로 PERL을 사용한 내 솔루션입니다. 환경 변수를 대체합니다.

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

여기에 있습니다 강력한 배쉬 기능 그 - 사용에도 불구하고 eval - 사용하기에 안전해야합니다.

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

다른 것은 없습니다 확장되었습니다 : 이름이있는 변수 참조도 없습니다 ~ 아니다 동봉 된 {...} (와 같은 $varName), 또는 명령 대체 ($(...) 레거시 구문 `...`), 또는 산술 대체 ($((...)) 레거시 구문 $[...]).

치료하려면 a $ 문자 그대로, \-에스케이프; 예 :\${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
}

함수는 NO를 가정합니다 0x1, 0x2, 0x3, 그리고 0x4 제어 문자는 입력에 존재합니다. 기능 프로세스 이후 내부적으로 사용됩니다 텍스트, 그것은 안전한 가정이어야합니다.

당신이 사용하기에 열려있는 경우 , 그것은 나의 제안이 될 것입니다. 아마도 약간있을 것입니다 sed 및/또는 어색한 아마도이 작업을 훨씬 쉽게하는 방법을 알고있는 전문가. 교체품을 위해 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 < yourfile | mysql

만들다 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

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

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

단일 바이너리로 컴파일되므로 시스템에 설치가 매우 쉽습니다.

그런 다음 다음과 같은 간단한 1 라이너를 수행 할 수 있습니다.

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

이것은보다 훨씬 안전합니다 eval 그리고 더 쉬운 그런 다음 Regex 또는 sed

나는 같은 것을 궁금해 하면서이 스레드를 찾았습니다. 그것은 나에게 이것에 영감을 주었다 (백 티크에주의를 기울여)

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

여기에 많은 선택이 있었지만 힙에 내 것을 던질 것이라고 생각했습니다. 그것은 perl 기반이며, $ {...} 양식의 변수 만 대상으로하고, 파일을 인수로 처리하고 stdout에서 변환 된 파일을 출력합니다.

use Env;
Env::import();

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

print "$text";

물론 나는 실제로 Perl 사람이 아니기 때문에 쉽게 치명적인 결함이있을 수 있습니다 (하지만 저에게 효과적입니다).

구성 파일 형식을 제어하면 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로 파이프하십시오. 데이터베이스를 파괴하지 않기를 바랍니다. :-).

다음은 파일의 내용이 이중 인용문 사이에 입력 된 것처럼 쉘이 귀하를 대체 할 수있는 방법입니다.

내용과 함께 template.txt의 예제 사용 :

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

다음 줄은 쉘이 template.txt의 내용을 보간하고 결과를 표준으로 작성하게합니다.

i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'

설명:

  • i 그리고 word 환경 변수가 sh.
  • sh 전달 된 문자열의 내용을 실행합니다.
  • 서로 옆에 쓰여진 문자열은 하나의 문자열이됩니다. 그 문자열은 다음과 같습니다.
    • 'echo "' + "$(cat template.txt)" + '"'
  • 대체는 사이에 있기 때문에 ", "$(cat template.txt)"출력이된다 cat template.txt.
  • 그래서 실행 된 명령 sh -c :
    • echo "The number is ${i}\nThe word is ${word}",
    • 어디 i 그리고 word 지정된 환경 변수입니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top