Bagaimana cara mengganti $ {} placeholder dalam file teks?

164

Saya ingin menyalurkan output file "template" ke MySQL, file yang memiliki variabel seperti ${dbName}diselingi. Apa utilitas baris perintah untuk mengganti instance ini dan membuang output ke output standar?

Dana si Sane
sumber

Jawaban:

192

Sed !

Template.txt yang diberikan:

Jumlahnya adalah $ {i}
Kata itu adalah $ {kata}

kita hanya harus mengatakan:

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

Terima kasih kepada Jonathan Leffler atas tipnya untuk meloloskan banyak -eargumen ke sedpermohonan yang sama .

pengguna
sumber
13
Anda dapat menggabungkan kedua perintah sed menjadi satu: sed -e "s / \ $ {i} / 1 /" -e "s / \ $ {word} / dog /"; itu lebih efisien. Anda dapat mengalami masalah dengan beberapa versi sed di mungkin 100 operasi seperti itu (masalah dari tahun lalu - mungkin masih belum benar, tetapi waspadalah HP-UX).
Jonathan Leffler
1
Terima kasih Jonathan, persis apa yang saya cari.
Dana the Sane
3
Petunjuk kecil: jika "1" atau "anjing" dalam contoh yang diberikan akan mengandung simbol dolar, Anda harus menghindarinya dengan backslash (jika tidak penggantian tidak terjadi).
MatthieuP
9
Anda juga tidak perlu cat. Yang Anda butuhkan hanyalah sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text.
HardlyKnowEm
3
Bagaimana jika teks pengganti adalah kata sandi? Dalam hal ini, sedakan mengharapkan teks yang lolos, yang merepotkan.
jpbochi
179

Memperbarui

Berikut ini adalah solusi dari yottatsa pada pertanyaan serupa yang hanya melakukan penggantian untuk variabel seperti $ VAR atau $ {VAR}, dan merupakan one-liner singkat

i=32 word=foo envsubst < template.txt

Tentu saja jika saya dan kata ada di lingkungan Anda, maka itu adil

envsubst < template.txt

Di Mac saya sepertinya diinstal sebagai bagian dari gettext dan dari MacGPG2

Jawaban Lama

Berikut ini adalah peningkatan solusi dari mogsie pada pertanyaan yang sama, solusi saya tidak mengharuskan Anda untuk mengawal tanda kutip ganda, mogsie tidak, tapi itu adalah satu liner!

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

Kekuatan pada dua solusi ini adalah bahwa Anda hanya mendapatkan beberapa jenis ekspansi shell yang tidak terjadi secara normal $ ((...)), `...`, dan $ (...), meskipun backslash adalah sebuah melarikan diri karakter di sini, tetapi Anda tidak perlu khawatir bahwa parsing memiliki bug, dan itu beberapa baris baik-baik saja.

plockc
sumber
6
Saya menemukan telanjang envsubsttidak berfungsi jika utusan Anda tidak diekspor.
Toddius Zho
4
@ToddiusZho: Tidak ada yang namanya variabel lingkungan yang tidak diekspor - justru ekspor yang menjadikan variabel shell variabel lingkungan. envsubst, seperti namanya, hanya mengenali variabel lingkungan , bukan variabel shell . Perlu juga dicatat bahwa envsubstini adalah utilitas GNU , dan karena itu tidak diinstal sebelumnya atau tersedia di semua platform.
mklement0
2
Mungkin cara lain untuk mengatakan adalah bahwa envsubst hanya melihat variabel lingkungan prosesnya sendiri, jadi variabel shell "normal" yang mungkin telah Anda tentukan sebelumnya (pada baris terpisah) tidak diwarisi oleh proses anak kecuali jika Anda "mengekspor" mereka. Dalam contoh penggunaan gettext di atas, saya memodifikasi lingkungan gettext yang diwarisi melalui mekanisme bash dengan mengawali mereka ke perintah yang akan saya jalankan
plockc
1
Saya memiliki satu string dengan $ HOME di dalamnya, saya menemukan $ HOME bekerja sebagai shell default untuk melakukannya, bukan $ HOME sebagai milik saya / home / zw963, tetapi, sepertinya tidak mendukung substitusi $ (cat / etc / hostname), jadi tidak lengkap sesuai permintaan saya sendiri.
zw963
3
Terima kasih untuk "Jawaban Lama", karena tidak hanya mengizinkan variabel, tetapi juga perintah shell seperti $ (ls -l)
Alek
46

Gunakan /bin/sh. Buat skrip shell kecil yang mengatur variabel, dan kemudian parsing templat menggunakan shell itu sendiri. Seperti itu (edit untuk menangani baris baru dengan benar):

File template.txt:

the number is ${i}
the word is ${word}

File 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"

Keluaran:

#sh script.sh
the number is 1
the word is dog
Agak
sumber
2
Mengapa tidak adil: sambil membaca baris; lakukan eval echo "$ line"; selesai <./template.txt ??? Tidak perlu membaca seluruh file ke dalam memori, hanya untuk memuntahkannya satu per satu melalui penggunaan intensif kepala dan ekor. Tetapi 'eval' tidak apa-apa - kecuali jika templat tersebut berisi karakter shell seperti kutipan kembali
Jonathan Leffler
16
Ini sangat berbahaya! Semua bashperintah dalam input akan dieksekusi. Jika templatnya adalah: "kata-katanya adalah; rm -rf $ HOME" Anda akan kehilangan file.
rzymek
1
@ rzymek - ingat, dia ingin mem-pipe file ini langsung ke database. Jadi tampaknya, inputnya dipercaya.
gnud
4
@gnud Ada perbedaan antara mempercayai file cukup untuk menyimpan kontennya dan cukup mempercayainya untuk menjalankan apa pun yang dikandungnya.
Markus
3
Untuk mencatat kendala: (a) tanda kutip ganda dalam input secara diam-diam dibuang, (b) readperintah, seperti yang tertulis, memotong spasi spasi awal dan akhir dari setiap baris dan \ karakter 'makan' ., (C) hanya menggunakan ini jika Anda sepenuhnya percaya atau mengontrol input, karena penggantian perintah ( `…` atau $(…)) yang tertanam dalam input memungkinkan eksekusi perintah sewenang-wenang karena penggunaan eval. Akhirnya, ada kemungkinan kecil bahwa echokesalahan awal baris untuk salah satu opsi baris perintah.
mklement0
23

Saya memikirkan hal ini lagi, mengingat minat baru-baru ini, dan saya pikir alat yang awalnya saya pikirkan adalah m4, prosesor makro untuk autotool. Jadi alih-alih variabel yang saya tentukan sebelumnya, Anda akan menggunakan:

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"
Dana si Sane
sumber
1
Solusi ini memiliki kelemahan paling sedikit dari jawaban di sini. Apakah Anda tahu cara mengganti $ {DBNAME} alih-alih hanya DBNAME?
Jack Davidson
@JackDavidson Saya akan menggunakan envsubstuntuk penggantian / templating variabel penggunaan sederhana ini, sebagaimana disebutkan dalam jawaban lain. m4adalah alat yang hebat, tetapi ini adalah preprocessor besar-besaran dengan lebih banyak fitur dan karenanya kompleksitas yang mungkin tidak diperlukan jika Anda hanya ingin mengganti beberapa variabel.
imiric
13

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
ChaPuZ
sumber
1
Seperti yang telah dicatat di tempat lain: Hanya gunakan ini jika Anda sepenuhnya mempercayai atau mengontrol input, karena penggantian perintah ( `…` atau $(…)) yang tertanam dalam input memungkinkan eksekusi perintah arbitrer karena penggunaan eval, dan eksekusi langsung kode shell karena penggunaan source. Juga, tanda kutip ganda dalam input secara diam-diam dibuang, dan echobisa keliru awal baris untuk salah satu opsi baris perintah.
mklement0
Sayangnya, ini menghapus semua tanda kutip ganda (") dari file hasil. Apakah ada cara untuk melakukan hal yang sama tanpa menghapus tanda kutip ganda?
Ivaylo Slavov
Saya menemukan apa yang saya cari di sini: stackoverflow.com/a/11050943/795158 ; Saya menggunakan envsubst. Perbedaannya adalah bahwa vars harus diekspor yang tidak masalah dengan saya.
Ivaylo Slavov
jika file teks mengandung "` "atau". " , subtitude akan gagal.
shuiqiang
12

Inilah fungsi Bash yang kuat yang - meskipun digunakan eval- harus aman digunakan.

Semua ${varName}referensi variabel dalam teks input diperluas berdasarkan variabel shell panggilan.

Tidak ada lagi yang diperluas: baik referensi variabel yang namanya tidak termasuk dalam {...}(seperti $varName), atau pergantian perintah ( $(...)dan sintaksis warisan `...`), atau pergantian aritmatika ( $((...))dan sintaksis warisan $[...]).

Untuk memperlakukan $sebagai literal, \-escape itu; misalnya:\${HOME}

Perhatikan bahwa input hanya diterima melalui stdin .

Contoh:

$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)

Kode sumber fungsi:

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
}

Fungsi ini mengasumsikan bahwa tidak ada 0x1, 0x2, 0x3, dan 0x4karakter kontrol yang hadir dalam input, karena mereka chars. digunakan secara internal - karena fungsi memproses teks , itu harus menjadi asumsi yang aman.

mklement0
sumber
2
Ini adalah salah satu jawaban terbaik di sini. Bahkan dengan menggunakannya evalpun cukup aman untuk digunakan.
anubhava
1
Solusi ini berfungsi dengan file JSON! (melarikan diri "dengan benar!)
WBAR
2
Suatu hal yang menyenangkan dengan solusi ini adalah itu akan membiarkan Anda memberikan default untuk variabel yang hilang ${FOO:-bar}atau hanya mengeluarkan sesuatu jika sudah disetel - ${HOME+Home is ${HOME}}. Saya menduga dengan sedikit ekstensi itu juga bisa mengembalikan kode keluar untuk variabel yang hilang ${FOO?Foo is missing}tetapi saat ini tidak tldp.org/LDP/abs/html/parameter-substitution.html memiliki daftar ini jika itu membantu
Stuart Moore
11

Buat rendertemplate.sh:

#!/usr/bin/env bash

eval "echo \"$(cat $1)\""

Dan template.tmpl:

Hello, ${WORLD}
Goodbye, ${CHEESE}

Render template:

$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl 
Hello, Foo
Goodbye, Bar
neu242
sumber
2
Ini menghapus string yang dikutip ganda
vrtx54234
Mencoba: eval "echo $ (cat $ 1)" - tanpa tanda kutip, dan itu berhasil untuk saya.
access_granted
2
Dari perspektif keamanan, ini adalah berita buruk. Jika template Anda berisi $(rm -rf ~), Anda menjalankannya sebagai kode.
Charles Duffy
eval "echo \"$(cat $1)\"" Bagus sekali!
dev devv
10

inilah solusi saya dengan perl berdasarkan jawaban sebelumnya, menggantikan variabel lingkungan:

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile
Thomas
sumber
2
Ini bagus. Tidak selalu memiliki perl, tetapi ketika Anda melakukannya, ini sederhana dan lurus ke depan.
Aaron McMillin
5

Jika Anda terbuka untuk menggunakan Perl , itu akan menjadi saran saya. Meskipun mungkin ada beberapa ahli sed dan / atau AWK yang mungkin tahu cara melakukan ini lebih mudah. Jika Anda memiliki pemetaan yang lebih kompleks dengan lebih dari sekadar dbName untuk pengganti Anda, Anda dapat memperpanjang ini dengan mudah, tetapi Anda mungkin juga memasukkannya ke skrip Perl standar pada saat itu.

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

Skrip Perl pendek untuk melakukan sesuatu yang sedikit lebih rumit (menangani beberapa tombol):

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

Jika Anda memberi nama skrip di atas sebagai skrip pengganti, skrip tersebut dapat digunakan sebagai berikut:

replace-script < yourfile | mysql
Beau Simensen
sumber
1
Bekerja untuk variabel tunggal, tetapi bagaimana saya memasukkan 'atau' untuk yang lain?
Dana Sane
2
Ada banyak cara Anda dapat melakukan ini dengan perl, semua tergantung pada seberapa rumit dan / atau amannya Anda ingin melakukan ini. Contoh yang lebih rumit dapat ditemukan di sini: perlmonks.org/?node_id=718936
Beau Simensen
3
Menggunakan perl jauh lebih bersih daripada mencoba menggunakan shell. Luangkan waktu untuk melakukan pekerjaan ini daripada mencoba beberapa solusi berbasis shell yang disebutkan lainnya.
jdigital
1
Baru-baru ini harus mengatasi masalah serupa. Pada akhirnya saya pergi dengan perl (envsubst tampak menjanjikan sedikit, tetapi itu terlalu sulit untuk dikendalikan).
sfitts
5

Berikut adalah cara untuk membuat shell melakukan substitusi untuk Anda, seolah-olah isi file tersebut diketik di antara tanda kutip ganda.

Menggunakan contoh template.txt dengan konten:

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

Baris berikut akan menyebabkan shell menginterpolasi isi template.txt dan menulis hasilnya ke standar.

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

Penjelasan:

  • i dan word diteruskan sebagai variabel lingkungan dicopot ke pelaksanaan sh.
  • sh mengeksekusi isi dari string yang dilewatkan.
  • String yang ditulis bersebelahan menjadi satu string, string itu adalah:
    • ' echo "' + " $(cat template.txt)" + ' "'
  • Karena substitusi adalah antara ", " $(cat template.txt)" menjadi output daricat template.txt .
  • Jadi perintah dijalankan oleh sh -c menjadi:
    • echo "The number is ${i}\nThe word is ${word}",
    • di mana idan wordmerupakan variabel lingkungan yang ditentukan.
Apriori
sumber
Dari perspektif keamanan, ini adalah berita buruk. Jika templat Anda berisi, katakanlah, '$(rm -rf ~)'$(rm -rf ~)kutipan literal dalam file templat akan cocok dengan yang Anda tambahkan sebelum perluasannya.
Charles Duffy
Saya tidak berpendapat bahwa in-template cocok dengan kutipan out-template, saya percaya shell menyelesaikan template dan in-terminal string secara mandiri (efektif menghilangkan tanda kutip) kemudian merangkai mereka. Versi tes yang tidak menghapus direktori home Anda adalah '$(echo a)'$(echo a). Itu menghasilkan 'a'a. Hal utama yang terjadi adalah bahwa bagian echo adalam pertama 'sedang dievaluasi, yang mungkin bukan yang Anda harapkan sejak itu ', tetapi perilaku yang sama seperti termasuk 'dalam "string yang dikutip.
Apriori
Jadi, ini tidak aman dalam arti memungkinkan pembuat template untuk mengeksekusi kode mereka. Namun bagaimana kutipan dievaluasi tidak benar-benar mempengaruhi keamanan. Memperluas apa pun yang "dikutip oleh string (termasuk $(...)) adalah intinya.
Apriori
Apakah itu intinya? Saya hanya melihat mereka meminta ${varname}, bukan yang lain, ekspansi risiko keamanan yang lebih tinggi.
Charles Duffy
... yang mengatakan, saya harus berbeda (re: in-template dan out-template quotes agar bisa cocok). Ketika Anda menempatkan tanda kutip tunggal di string Anda, Anda membelah menjadi string yang dikutip tunggal echo ", diikuti oleh string yang dikutip ganda dengan rangkaian literal template.txt, diikuti oleh string literal lain ", semua disatukan menjadi argumen tunggal yang diteruskan sh -c. Anda benar bahwa 'tidak dapat dicocokkan (karena dikonsumsi oleh kulit terluar daripada diteruskan ke kulit dalam), tetapi "pasti bisa, sehingga templat yang berisi Gotcha"; rm -rf ~; echo "dapat dieksekusi.
Charles Duffy
4

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
pengguna976433
sumber
2
Ini tidak aman karena akan menjalankan pergantian perintah dalam template jika mereka memiliki contoh backslash terkemuka\$(date)
Peter Dolberg
1
Selain dari titik valid Peter: Saya sarankan Anda menggunakan while IFS= read -r line; dosebagai readperintah, jika tidak, Anda akan menghapus spasi spasi awal dan akhir dari setiap baris input. Juga, echobisa keliru awal baris untuk salah satu opsi baris perintah, jadi lebih baik digunakan printf '%s\n'. Akhirnya, lebih aman untuk mengutip ganda ${1}.
mklement0
4

Saya akan menyarankan menggunakan sesuatu seperti Sigil : https://github.com/gliderlabs/sigil

Ini dikompilasi ke biner tunggal, jadi sangat mudah untuk menginstal pada sistem.

Maka Anda dapat melakukan satu-liner sederhana seperti berikut:

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

Ini jauh lebih aman daripada evaldan lebih mudah menggunakan regex ataused

spudfkc
sumber
2
Jawaban bagus! Ini adalah sistem templating yang tepat dan jauh lebih mudah untuk dikerjakan daripada jawaban lainnya.
Erfan
BTW, lebih baik untuk menghindari catdan menggunakan <my-file.conf.templatesebagai gantinya Anda memberikan sigilpegangan file nyata daripada FIFO.
Charles Duffy
2

Saya menemukan utas ini sambil bertanya-tanya hal yang sama. Itu mengilhami saya untuk ini (hati-hati dengan backticks)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
GlueC
sumber
4
Singkatan bash $(cat file)adalah$(< file)
glenn jackman
3
Tampaknya metode ini mengacaukan jeda baris, yaitu file saya digema semua dalam satu baris.
Arthur Corenzan
@ArthurCorenzan: Memang, jeda baris diganti dengan spasi. Untuk memperbaikinya, Anda harus menggunakan eval echo "\"$(cat FILE)\""tetapi itu mungkin masih gagal karena tanda kutip ganda pada input dibuang.
mklement0
Seperti yang telah dicatat di tempat lain: Hanya gunakan ini jika Anda sepenuhnya mempercayai atau mengontrol input, karena penggantian perintah ( `…` atau $(…)) yang tertanam dalam input memungkinkan eksekusi perintah sewenang-wenang karena penggunaan eval.
mklement0
2

Banyak pilihan di sini, tapi kupikir aku akan melemparkan milikku di atas tumpukan. Berbasis perl, hanya variabel target dari formulir $ {...}, yang akan memproses file sebagai argumen dan menampilkan file yang dikonversi di stdout:

use Env;
Env::import();

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

print "$text";

Tentu saja saya bukan orang yang benar-benar perl, jadi bisa saja ada kesalahan fatal (bekerja untuk saya).

sfitt
sumber
1
Bekerja dengan baik. Anda dapat menghentikannya Env::import();- mengimpor tersirat oleh use. Juga, saya sarankan untuk tidak membangun seluruh output dalam memori terlebih dahulu: cukup gunakan print;alih-alih $text .= $_;di dalam loop, dan lepaskan perintah post-loop print.
mklement0
1

Ini dapat dilakukan dalam bash sendiri jika Anda memiliki kontrol format file konfigurasi. Anda hanya perlu sumber (".") File konfigurasi daripada subshell itu. Itu memastikan variabel dibuat dalam konteks shell saat ini (dan terus ada) daripada subshell (di mana variabel menghilang ketika subshell keluar).

$ 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

Jika file config Anda tidak bisa berupa skrip shell, Anda bisa 'mengompilasinya' sebelum menjalankannya (kompilasi tergantung pada format input Anda).

$ 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

Dalam kasus spesifik Anda, Anda dapat menggunakan sesuatu seperti:

$ 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

Kemudian kirimkan output go.bash ke MySQL dan voila, semoga Anda tidak akan menghancurkan database Anda :-).

paxdiablo
sumber
1
Anda tidak perlu mengekspor variabel dari file config.data; itu cukup hanya dengan mengaturnya. Anda juga sepertinya tidak membaca file templat kapan pun. Atau, mungkin, file templat diubah dan berisi operasi 'gema' ... atau apakah saya kehilangan sesuatu?
Jonathan Leffler
1
Poin bagus pada ekspor, saya melakukan itu secara default sehingga mereka tersedia untuk subkulit dan itu tidak membahayakan karena mereka mati ketika keluar. File 'template' adalah skrip itu sendiri dengan pernyataan gema itu. Tidak perlu memperkenalkan file ketiga - ini pada dasarnya adalah operasi tipe mailmerge.
paxdiablo
1
"Script itu sendiri dengan pernyataan gema itu" bukan templat: ini skrip. Pikirkan perbedaan readibility (dan rawatan) antara <xml type = "$ TYPE"> dan echo '<xml type = "' $ TYPE '">'
Pierre-Olivier Vares
1
@Pierre, tidak ada pernyataan gema di skrip konfigurasi saya, itu hanya ekspor, dan saya telah menunjukkan bagaimana Anda dapat menghindarinya bahkan dengan jumlah pra-pemrosesan yang minimal. Jika Anda berbicara tentang pernyataan gema di skrip saya yang lain (seperti go.bash), Anda salah paham - mereka bukan bagian dari solusi, mereka hanya cara untuk menunjukkan bahwa variabel sedang diatur dengan benar.
paxdiablo
1
@paxdiablo: Sepertinya Anda baru saja lupa pertanyaan: << Saya ingin menyalurkan output file "template" ke MySQL >>. Jadi penggunaan template ADALAH pertanyaan, itu bukan "ujung tongkat yang salah". Mengekspor variabel dan menggemakannya dalam skrip lain sama sekali tidak menjawab pertanyaan sama sekali
Pierre-Olivier Vares
0

Di tempat perl mengedit beberapa file berpotensi, dengan cadangan.

  perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
    -i.orig \
    -p config/test/*
joehep
sumber
0

Anda akan menginginkan sesuatu yang lebih kuat daripada saran saat ini karena sementara mereka bekerja untuk kasus penggunaan terbatas Anda (untuk saat ini), mereka tidak akan cukup untuk situasi yang lebih kompleks.

Anda membutuhkan penyaji yang lebih baik. Anda membutuhkan penyaji terbaik. Anda membutuhkan Yang Renderest!

Template.txt yang diberikan:

Halo, {{person}}!

Lari:

$ person = Bob ./render template.txt

Dan Anda akan melihat hasilnya

Halo, Bob!

Tulis ke file dengan mengarahkan stdout ke file:

$ person = Bob ./render template.txt> rendered.txt

Dan jika Anda membuat skrip yang memiliki variabel $ {} yang tidak ingin Anda interpolasi, The Renderest membuat Anda dilindungi tanpa harus melakukan hal lain!

Lanjutkan dan dapatkan salinan Anda di https://github.com/relaxdiego/renderest

Mark Maglana
sumber