質問

" template"の出力をパイプしたい $ {dbName} のような変数が散在するファイルにMySQLに保存します。これらのインスタンスを置き換え、出力を標準出力にダンプするコマンドラインユーティリティとは何ですか?

役に立ちましたか?

解決

Sed

指定されたtemplate.txt:

The number is ${i}
The word is ${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 word があれば、それはただ

envsubst < template.txt

Macでは、 gettext の一部として、および MacGPG2

からインストールされたように見えます

古い回答

同様の質問に対する mogsie からのソリューションの改善点です。私のソリューションでは、二重にスケールする必要はありません。 mogsieは引用していますが、彼は1つのライナーです!

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

これらの2つのソリューションの利点は、通常は発生しない少数のタイプのシェル拡張のみを取得することです。ただし、$((...))、 `...`、および$(...)ここではバックスラッシュは エスケープ文字ですが、解析にバグがあることを心配する必要はなく、複数行で問題ありません。

/ bin / sh を使用します。変数を設定する小さなシェルスクリプトを作成し、シェル自体を使用してテンプレートを解析します。そのようにします(改行を正しく処理するために編集します):

file 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 を使用しても安全に使用できる堅牢なBash関数があります。

入力テキスト内のすべての $ {varName} 変数参照は、呼び出しシェルの変数に基づいて展開されます。

他に何も展開されません:名前が not {...} で囲まれた変数参照( $など) varName )、コマンド置換( $(...)およびレガシー構文 `...` )、算術置換( $( (...))および従来の構文 $ [...] )。

$ をリテラルとして扱うには、 \ -escape;例: \ $ {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 '`([

この関数は、 0x1 0x2 0x3 、および 0x4 の制御文字がないことを前提としていますこれらの文字のため、入力に存在します。内部的に使用されます-この関数は text を処理するため、これは安全な前提となるはずです。

'\1\2\3\4') # ... then selectively reenable ${ references lineEscaped=${lineEscaped//

この関数は、 0x1 0x2 0x3 、および 0x4 の制御文字がないことを前提としていますこれらの文字のため、入力に存在します。内部的に使用されます-この関数は text を処理するため、これは安全な前提となるはずです。

\4'{/\${} # Finally, escape embedded double quotes to preserve them. lineEscaped=${lineEscaped//\"/\\\"} eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([

この関数は、 0x1 0x2 0x3 、および 0x4 の制御文字がないことを前提としていますこれらの文字のため、入力に存在します。内部的に使用されます-この関数は text を処理するため、これは安全な前提となるはずです。

done }

この関数は、 0x1 0x2 0x3 、および 0x4 の制御文字がないことを前提としていますこれらの文字のため、入力に存在します。内部的に使用されます-この関数は text を処理するため、これは安全な前提となるはずです。

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/\$\{

Perl の使用を受け入れている場合、それが私の提案です。おそらく sed AWK のエキスパートは、おそらくこれをはるかに簡単にする方法を知っているでしょう。置換用のdbNameだけでなく、より複雑なマッピングがある場合、これを非常に簡単に拡張できますが、その時点で標準のPerlスクリプトに配置することもできます。

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

もう少し複雑なことを行う(複数のキーを処理する)短いPerlスクリプト:

replace-script < yourfile | mysql

上記のスクリプトにreplace-scriptという名前を付けると、次のように使用できます。

<*>\}/$replace{

Perl の使用を受け入れている場合、それが私の提案です。おそらく sed AWK のエキスパートは、おそらくこれをはるかに簡単にする方法を知っているでしょう。置換用のdbNameだけでなく、より複雑なマッピングがある場合、これを非常に簡単に拡張できますが、その時点で標準のPerlスクリプトに配置することもできます。

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

もう少し複雑なことを行う(複数のキーを処理する)短いPerlスクリプト:

<*>

上記のスクリプトにreplace-scriptという名前を付けると、次のように使用できます。

<*>}/g for keys %replace; print $buf;

上記のスクリプトにreplace-scriptという名前を付けると、次のように使用できます。

<*>

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

Sigil のようなものを使用することをお勧めします。      https://github.com/gliderlabs/sigil

単一のバイナリにコンパイルされるため、システムへのインストールは非常に簡単です。

その後、次のような簡単なワンライナーを実行できます。

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(<>) { 

ここには多くの選択肢がありますが、私はヒープ上で私のものを投げると思いました。 perlベースで、$ {...}の形式の変数のみを対象とし、ファイルを引数として処理し、変換されたファイルをstdoutに出力します。

<*>

もちろん、私は実際にはperlの人間ではないので、致命的な欠陥が簡単に発生する可能性があります(私にとってはうまくいきます)。

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

ここには多くの選択肢がありますが、私はヒープ上で私のものを投げると思いました。 perlベースで、$ {...}の形式の変数のみを対象とし、ファイルを引数として処理し、変換されたファイルをstdoutに出力します。

<*>

もちろん、私は実際にはperlの人間ではないので、致命的な欠陥が簡単に発生する可能性があります(私にとってはうまくいきます)。

; } print "$text";

もちろん、私は実際にはperlの人間ではないので、致命的な欠陥が簡単に発生する可能性があります(私にとってはうまくいきます)。

構成ファイル形式を制御できる場合、bash自体で実行できます。構成ファイルをサブシェル化するのではなく、ソース(&quot;。&quot;)するだけです。これにより、変数はサブシェル(サブシェルが終了すると変数が消える)ではなく、現在のシェルのコンテキストで作成され(存在し続ける)ことが保証されます。

$ 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 '^

特定のケースでは、次のようなものを使用できます:

$ 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と出来上がりにパイプします。データベースを破壊しないことを願っています:-)。

| 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

特定のケースでは、次のようなものを使用できます:

<*>

次にgo.bashの出力をMySQLと出来上がりにパイプします。データベースを破壊しないことを願っています:-)。

これは、代わりにファイルの内容が二重引用符の間に入力されたかのように、シェルに置換を行わせる方法です。

内容を含む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 は、渡された文字列の内容を実行します。
  • 互いに隣り合って記述された文字列は1つの文字列になります。
    • ' echo&quot; ' +&quot; $(cat template.txt)&quot; + '&quot; '
  • 置換は&quot; と&quot; $(cat template.txt)&quot;の間にあるため、 cat template.txt の出力になります。
  • したがって、 sh -c によって実行されるコマンドは次のようになります。
    • echo&quot;数字は$ {i} \ n単語は$ {word}&quot;
    • i および word は、指定された環境変数です。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top