テキストファイルに同じ名前の環境変数を含むプレースホルダを展開しますか?

テキストファイルに同じ名前の環境変数を含むプレースホルダを展開しますか?

この質問にはさまざまなバリエーションがありますが、とにかくこの問題に対する解決策を見つけるのに非常に近づいていたので(!)ここに質問したいと思いました。少しの努力だけが必要です。

想像する

HerokuでホストされているPostgresデータベースのレポートを実行するために使用するいくつかのテキストSQLファイルがあります。現在のSQLファイルの1つは次のとおりです。

SELECT
  (SELECT COUNT(*) FROM metrics WHERE(organization_id = o.id AND year = ${sql_year})) AS metrics,
  (SELECT COUNT(*) FROM my_metrics WHERE(organization_id = o.id)) AS quarterly_metrics,
  (SELECT COUNT(*) FROM quarterly_metrics WHERE(organization_id = o.id AND year = ${sql_year})) AS quarterly_metrics,
  (SELECT COUNT(*) FROM quarterly_text_metrics WHERE(organization_id = o.id AND year = ${sql_year})) AS quarterly_text_metrics,
  (SELECT COUNT(*) FROM budgets WHERE(organization_id = o.id AND year = ${sql_year})) AS budgets,
  (SELECT COUNT(*) FROM goals WHERE(goalable_type = 'Organization' AND goalable_id = o.id AND year = ${sql_year})) AS goals
FROM
  organizations AS o
WHERE
  o.id = ${sql_org_id}
;

私はできます。良い次のプロセスを使用します。

export sql_org_id=1; export sql_year=2013
cat reports/my_report.sql | sed -e "s/\(\${[a-zA-Z_]*}\)/`eval "echo '\1'"`/" | heroku pg:psql

これにより、SQLをHerokuにパイプしてレポートを生成し、すべての変数をスクリプトを実行する前にエクスポートされた対応するENV変数に置き換えることができます。したがって、SQLファイルを編集するのではなく、即座に変数を変更して別のレポートを実行できます。

私の質問

だから質問は私ですほぼそこにありますが、私はそれをよく理解していません。私の表現は、次のように使用すると機能しますsedecho

export sql_year=2013
echo "SELECT ${sql_year} AS year" | sed -e "s/\(\${[a-zA-Z_]*}\)/`eval "echo '\1'"`/"

catただし、ファイル全体の内容を処理することはできません。

export sql_org_id=1; export sql_year=2013
cat reports/my_report.sql | sed -e "s/\(\${[a-zA-Z_]*}\)/`eval "echo '\1'"`/"

sedと一緒に使用すると何か抜けましたかcat?助けてください!

修正する:私はMac OS X 10.8を使用しています。

ベストアンサー1

そしてzsh

print -r -- "${(e)$(<reports/my_report.sql)}"

Bourneに似たシェルの場合(含むzsh):

eval "cat << EOF
$(cat reports/my_report.sql)
EOF"

`...`両方とも、、、$(...)およびを$((...))拡張します。したがって、拡張したくないドル文字とバックティック文字をエスケープする必要があります。$[...]$xxx${xxx}

また、2番目のファイルの内容には3文字の行を含めないでくださいEOFSQL問題ではありません)。

または、次のことができます。

perl -pe 's/\${(\w+)}/$ENV{$1}/g' reports/my_report.sql

exportこれを理解するには、これらの変数が必要ですperl

解決策が機能せず、まったく機能しない理由については、後で実行してset -x何が起こっているのかを確認できます。

$ echo "SELECT ${sql_year} AS year" | sed -e "s/\(\${[a-zA-Z_]*}\)/`eval "echo '\1'"`/"
+ echo 'SELECT 2013 AS year'
++ eval 'echo '\''\1'\'''
+++ echo '\1'
+ sed -e 's/\(${[a-zA-Z_]*}\)/\1/'
SELECT 2013 AS year

二重引用符を使用すると、シェルはおよびをecho呼び出す前に変数とコマンドの置換を拡張しますsed。したがって、実際に次のことを実行しました。

echo 'SELECT 2013 AS year' | sed -e 's/\(${[a-zA-Z_]*}\)/\1/'

sedコードを実行できません。したがって、一重引用符を使用してもsed拡張されません`...`

おすすめ記事