200

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

4

18 に答える 18

232

セド

与えられた template.txt:

番号は ${i} です
単語は ${word} です

私たちはただ言う必要があります:

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

-e複数の引数を同じsed呼び出しに渡すためのヒントをくれた Jonathan Leffler に感謝します。

于 2009-01-06T08:01:21.887 に答える
231

アップデート

$VAR や ${VAR} などの変数の置換のみを行い、簡単なワンライナーである同様の質問に対するyottatsaの解決策を次に示します。

i=32 word=foo envsubst < template.txt

もちろん、iwordがあなたの環境にある場合は、

envsubst < template.txt

私のMacでは、gettextの一部としてMacGPG2からインストールされたようです

古い回答

これは、同様の質問に対するmogsieからのソリューションの改善です。私のソリューションでは、二重引用符をエスケールする必要はありません.mogsieはそうしますが、彼はワンライナーです!

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

これら 2 つのソリューションの利点は、通常では発生しないシェル展開のいくつかのタイプしか得られないことです。$((...))、`...`、および $(... )。ここではエスケープ文字を使用しますが、解析にバグがあることを心配する必要はなく、複数行を問題なく実行できます。

于 2013-06-10T19:03:05.807 に答える
49

を使用し/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
于 2009-01-06T07:10:06.593 に答える
24

最近の興味から改めて考えてみたのですが、もともと考えていたツールはm4autotools のマクロプロセッサだったと思います。したがって、最初に指定した変数の代わりに、次を使用します。

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"
于 2011-05-19T15:19:00.497 に答える
16

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
于 2009-08-20T21:31:19.467 に答える
13

これは、使用しても安全に使用できる堅牢な Bash 関数です。eval

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

名前が囲まれていない変数参照{...}( など$varName)、コマンド置換 ($(...)および 従来の構文`...`)、算術置換 ($((...))および 従来の構文) は展開されませ$[...]

$a をリテラルとして扱うには、 \-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この関数は、 、0x20x3、および0x4制御文字が入力に存在しないことを前提としています。は内部で使用されます - 関数はtextを処理するため、これは安全な仮定です。

于 2016-10-21T03:31:10.960 に答える
12

以前の回答に基づいたperlを使用した私のソリューションは、環境変数を置き換えます:

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile
于 2013-06-06T15:32:34.190 に答える
6

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

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

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

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

これはeval、正規表現やsed

于 2016-02-23T20:44:52.233 に答える
6

ファイルの内容が代わりに二重引用符で囲まれて入力されたかのように、シェルに置換を実行させる方法を次に示します。

コンテンツを含む template.txt の例を使用すると、次のようになります。

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

次の行により、シェルは template.txt の内容を補間し、結果を標準出力に書き込みます。

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

説明:

  • iword実行にスコープされた環境変数として渡されますsh
  • sh渡された文字列の内容を実行します。
  • 隣り合わせに書かれた文字列は 1 つの文字列になります。その文字列は次のとおりです。
    • ' echo "' + " $(cat template.txt)" + ' "'
  • の間で置換されているため"、" $(cat template.txt)" は の出力となりますcat template.txt
  • したがって、によって実行されるコマンドは次のようにsh -cなります。
    • echo "The number is ${i}\nThe word is ${word}"
    • とはiword指定された環境変数です。
于 2019-03-30T03:03:41.163 に答える
5

もしあなたがPerlを使うことにオープンであるなら、それは私の提案でしょう。おそらく、これをはるかに簡単に行う方法を知っているsedAWKの専門家がいるでしょう。置換用の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
于 2009-01-06T07:08:45.003 に答える
4

ファイル.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
于 2011-10-03T10:08:31.220 に答える
2

同じことを考えていたところ、このスレッドを見つけました。これは私にインスピレーションを与えました(バッククォートに注意してください)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
于 2011-05-16T04:09:11.057 に答える
2

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

use Env;
Env::import();

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

print "$text";

もちろん、私は実際には perl の人ではないので、致命的な欠陥が簡単に存在する可能性があります (ただし、私には機能します)。

于 2014-07-12T01:55:27.380 に答える
1

構成ファイル形式を制御できる場合は、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 と出来上がりにパイプします。データベースを破壊しないことを願っています :-)。

于 2009-01-06T07:49:59.117 に答える
0

私にとってこれは最も簡単で強力なソリューションです。同じコマンドを使用して他のテンプレートを含めることもできますeval echo "$(<template.txt)

ネストされたテンプレートの例

  1. テンプレート ファイルを作成します。変数は通常の bash 構文${VARIABLE_NAME}または$VARIABLE_NAME

\テンプレートで特殊文字をエスケープする必要があります。そうしないと、 によって解釈されevalます。

template.txt

Hello ${name}!
eval echo $(<nested-template.txt)

nested-template.txt

Nice to have you here ${name} :\)
  1. ソースファイルを作成する

template.source

declare name=royman 
  1. テンプレートをパースする
source template.source && eval echo "$(<template.txt)"
  1. 出力
Hello royman!
Nice to have you here royman :)

于 2022-02-19T18:18:04.687 に答える
0

潜在的に複数のファイルを perl で編集し、バックアップを行います。

  perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
    -i.orig \
    -p config/test/*
于 2020-02-03T21:12:34.107 に答える
0

という名前のシェル テンプレート スクリプトを作成しましたshtpl。私shtplはジンジャのような構文を使用しています。これは、ansible を頻繁に使用するようになったので、よく知っています。

$ cat /tmp/test
{{ aux=4 }}
{{ myarray=( a b c d ) }}
{{ A_RANDOM=$RANDOM }}
$A_RANDOM
{% if $(( $A_RANDOM%2 )) == 0 %}
$A_RANDOM is even
{% else %}
$A_RANDOM is odd
{% endif %}
{% if $(( $A_RANDOM%2 )) == 0 %}
{% for n in 1 2 3 $aux %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/passwd field #$n: $(grep $USER /etc/passwd | cut -d: -f$n)
{% endfor %}
{% else %}
{% for n in {1..4} %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/group field #$n: $(grep ^$USER /etc/group | cut -d: -f$n)
{% endfor %}
{% endif %}


$ ./shtpl < /tmp/test
6535
6535 is odd
$myarray[0]: a
/etc/group field #1: myusername
$myarray[1]: b
/etc/group field #2: x
$myarray[2]: c
/etc/group field #3: 1001
$myarray[3]: d
/etc/group field #4: 

私のgithubの詳細

于 2021-01-14T08:25:57.087 に答える