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?
bash
command-line
text-processing
templating
Dana si Sane
sumber
sumber
cat
. Yang Anda butuhkan hanyalahsed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
.sed
akan mengharapkan teks yang lolos, yang merepotkan.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
Tentu saja jika saya dan kata ada di lingkungan Anda, maka itu adil
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!
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.
sumber
envsubst
tidak berfungsi jika utusan Anda tidak diekspor.envsubst
, seperti namanya, hanya mengenali variabel lingkungan , bukan variabel shell . Perlu juga dicatat bahwaenvsubst
ini adalah utilitas GNU , dan karena itu tidak diinstal sebelumnya atau tersedia di semua platform.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:
File script.sh:
Keluaran:
sumber
bash
perintah dalam input akan dieksekusi. Jika templatnya adalah: "kata-katanya adalah; rm -rf $ HOME" Anda akan kehilangan file.read
perintah, 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 penggunaaneval
. Akhirnya, ada kemungkinan kecil bahwaecho
kesalahan awal baris untuk salah satu opsi baris perintah.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:sumber
envsubst
untuk penggantian / templating variabel penggunaan sederhana ini, sebagaimana disebutkan dalam jawaban lain.m4
adalah 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.template.txt
data.sh
parser.sh
parsed_file.txt
sumber
`…`
atau$(…)
) yang tertanam dalam input memungkinkan eksekusi perintah arbitrer karena penggunaaneval
, dan eksekusi langsung kode shell karena penggunaansource
. Juga, tanda kutip ganda dalam input secara diam-diam dibuang, danecho
bisa keliru awal baris untuk salah satu opsi baris perintah.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:
Kode sumber fungsi:
Fungsi ini mengasumsikan bahwa tidak ada
0x1
,0x2
,0x3
, dan0x4
karakter kontrol yang hadir dalam input, karena mereka chars. digunakan secara internal - karena fungsi memproses teks , itu harus menjadi asumsi yang aman.sumber
eval
pun cukup aman untuk digunakan."
dengan benar!)${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 membantuBuat
rendertemplate.sh
:Dan
template.tmpl
:Render template:
sumber
$(rm -rf ~)
, Anda menjalankannya sebagai kode.eval "echo \"$(cat $1)\""
Bagus sekali!inilah solusi saya dengan perl berdasarkan jawaban sebelumnya, menggantikan variabel lingkungan:
sumber
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.
Skrip Perl pendek untuk melakukan sesuatu yang sedikit lebih rumit (menangani beberapa tombol):
Jika Anda memberi nama skrip di atas sebagai skrip pengganti, skrip tersebut dapat digunakan sebagai berikut:
sumber
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:
Baris berikut akan menyebabkan shell menginterpolasi isi template.txt dan menulis hasilnya ke standar.
Penjelasan:
i
danword
diteruskan sebagai variabel lingkungan dicopot ke pelaksanaansh
.sh
mengeksekusi isi dari string yang dilewatkan.echo "
' + "$(cat template.txt)
" + '"
'"
, "$(cat template.txt)
" menjadi output daricat template.txt
.sh -c
menjadi:echo "The number is ${i}\nThe word is ${word}"
,i
danword
merupakan variabel lingkungan yang ditentukan.sumber
'$(rm -rf ~)'$(rm -rf ~)
kutipan literal dalam file templat akan cocok dengan yang Anda tambahkan sebelum perluasannya.'$(echo a)'$(echo a)
. Itu menghasilkan'a'a
. Hal utama yang terjadi adalah bahwa bagianecho a
dalam pertama'
sedang dievaluasi, yang mungkin bukan yang Anda harapkan sejak itu'
, tetapi perilaku yang sama seperti termasuk'
dalam"
string yang dikutip."
dikutip oleh string (termasuk$(...)
) adalah intinya.${varname}
, bukan yang lain, ekspansi risiko keamanan yang lebih tinggi.echo "
, diikuti oleh string yang dikutip ganda dengan rangkaian literaltemplate.txt
, diikuti oleh string literal lain"
, semua disatukan menjadi argumen tunggal yang diteruskansh -c
. Anda benar bahwa'
tidak dapat dicocokkan (karena dikonsumsi oleh kulit terluar daripada diteruskan ke kulit dalam), tetapi"
pasti bisa, sehingga templat yang berisiGotcha"; rm -rf ~; echo "
dapat dieksekusi.file.tpl:
script.sh:
sumber
\$(date)
while IFS= read -r line; do
sebagairead
perintah, jika tidak, Anda akan menghapus spasi spasi awal dan akhir dari setiap baris input. Juga,echo
bisa keliru awal baris untuk salah satu opsi baris perintah, jadi lebih baik digunakanprintf '%s\n'
. Akhirnya, lebih aman untuk mengutip ganda${1}
.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:
Ini jauh lebih aman daripada
eval
dan lebih mudah menggunakan regex ataused
sumber
cat
dan menggunakan<my-file.conf.template
sebagai gantinya Anda memberikansigil
pegangan file nyata daripada FIFO.Saya menemukan utas ini sambil bertanya-tanya hal yang sama. Itu mengilhami saya untuk ini (hati-hati dengan backticks)
sumber
$(cat file)
adalah$(< file)
eval echo "\"$(cat FILE)\""
tetapi itu mungkin masih gagal karena tanda kutip ganda pada input dibuang.`…`
atau$(…)
) yang tertanam dalam input memungkinkan eksekusi perintah sewenang-wenang karena penggunaaneval
.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:
Tentu saja saya bukan orang yang benar-benar perl, jadi bisa saja ada kesalahan fatal (bekerja untuk saya).
sumber
Env::import();
- mengimpor tersirat olehuse
. Juga, saya sarankan untuk tidak membangun seluruh output dalam memori terlebih dahulu: cukup gunakanprint;
alih-alih$text .= $_;
di dalam loop, dan lepaskan perintah post-loopprint
.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).
Jika file config Anda tidak bisa berupa skrip shell, Anda bisa 'mengompilasinya' sebelum menjalankannya (kompilasi tergantung pada format input Anda).
Dalam kasus spesifik Anda, Anda dapat menggunakan sesuatu seperti:
Kemudian kirimkan output go.bash ke MySQL dan voila, semoga Anda tidak akan menghancurkan database Anda :-).
sumber
go.bash
), Anda salah paham - mereka bukan bagian dari solusi, mereka hanya cara untuk menunjukkan bahwa variabel sedang diatur dengan benar.Di tempat perl mengedit beberapa file berpotensi, dengan cadangan.
sumber
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
sumber