Saya memiliki string multi-baris ini (termasuk kutipan):
abc'asdf"
$(dont-execute-this)
foo"bar"''
Bagaimana saya menetapkannya ke variabel menggunakan heredoc di Bash?
Saya perlu mempertahankan baris baru.
Saya tidak ingin lepas dari karakter dalam string, itu akan mengganggu ...
'EOF'
, dengan linebreak lolos dengan` in the content: if the second line has
perintah cd`, saya kembali: " .sh: baris X: cd: perintah tidak ditemukan "; tetapi jika saya double-quote"EOF"
; kemudian variabel bash${A}
tidak bisa dipertahankan sebagai string (mereka bisa diperluas); tapi kemudian, line-break yang diawetkan - dan, saya tidak memiliki masalah menjalankan perintah dengancd
di baris kedua ( dan kedua 'EOF' dan "EOF" tampaknya bermain dengan baik juga denganeval
, untuk menjalankan sekumpulan perintah yang tersimpan di variabel string ). Bersulang!"EOF"
variabel qouted ganda , jika dipanggil viaeval $VAR
, akan menyebabkan semua skrip lainnya dikomentari, karena di sini $ VAR akan dilihat sebagai satu baris ; untuk dapat menggunakan#
komentar bash dalam skrip multiline, kutipan ganda juga variabel dalameval call:
eval "$ VAR" `.eval
ith metode ini, tetapi tidak melacaknya karena itu adalah bagian dari beberapa paket yangeval
beberapa variabel didefinisikan dalam file konfigurasi itu. Pesan kesalahan adalah:/usr/lib/network/network: eval: line 153: syntax error: unexpected end of file
. Saya baru saja beralih ke solusi lain.Jawaban:
Anda dapat menghindari penggunaan yang tidak berguna
cat
dan menangani penawaran yang tidak cocok lebih baik dengan ini:Jika Anda tidak mengutip variabel ketika Anda menggemakannya, baris baru hilang. Mengutip itu melindungi mereka:
Jika Anda ingin menggunakan indentasi untuk keterbacaan dalam kode sumber, gunakan tanda hubung setelah less-thans. Lekukan harus dilakukan hanya menggunakan tab (tanpa spasi).
Jika, sebagai gantinya, Anda ingin mempertahankan tab di isi dari variabel yang dihasilkan, Anda perlu menghapus tab dari
IFS
. Penanda terminal untuk doc di sini (EOF
) tidak boleh diindentasi.Tab dapat dimasukkan pada baris perintah dengan menekan Ctrl- V Tab. Jika Anda menggunakan editor, tergantung yang mana, itu mungkin juga berfungsi atau Anda mungkin harus mematikan fitur yang secara otomatis mengubah tab menjadi spasi.
sumber
set -o errexit
(aliasset -e
) dalam skrip Anda dan Anda menggunakan ini maka itu akan menghentikan skrip Anda karenaread
mengembalikan kode pengembalian tidak nol ketika mencapai EOF.set -e
dan selalu merekomendasikan untuk tidak menggunakannya. Lebih baik menggunakan penanganan kesalahan yang tepat sebagai gantinya.trap
adalah temanmu Teman-teman lain:else
dan di||
antara yang lainnya.cat
benar-benar layak dalam kasus seperti itu? Menugaskan heredoc ke variabel dengancat
adalah idiom yang terkenal. Entah bagaimana menggunakanread
hal-hal mengaburkan untuk sedikit manfaat imho.d
dan string kosong;bash
runtuh-rd''
untuk hanya-rd
sebelumread
melihat argumennya, jadiVAR
diperlakukan sebagai argumen untuk-d
.read
akan kembali dengan kode keluar yang tidak nol. Ini membuat metode ini kurang ideal dalam skrip dengan pemeriksaan kesalahan diaktifkan (misset -e
.).Gunakan $ () untuk menetapkan output
cat
ke variabel Anda seperti ini:Pastikan untuk membatasi mulai END_HEREDOC dengan tanda kutip tunggal.
Perhatikan bahwa mengakhiri pembatas heredoc
END_HEREDOC
harus sendirian di baris (maka tanda kurung berakhir di baris berikutnya).Terima kasih
@ephemient
atas jawabannya.sumber
echo "$VAR"
bukannyaecho $VAR
.ash
dan OpenWRTread
tidak mendukung-d
.ini adalah variasi dari metode Dennis, terlihat lebih elegan dalam skrip.
definisi fungsi:
pemakaian:
Nikmati
ps membuat versi 'read loop' untuk shell yang tidak mendukung
read -d
. harus bekerja denganset -eu
dan backticks tidak berpasangan , tetapi tidak diuji dengan sangat baik:sumber
read
loop dalam fungsi, untuk menghindari-d ''
bashism yang diperlukan untuk mempertahankan baris baru).set -e
set, sedangkan jawaban yang dipilih tidak. Tampaknya karenahttp://unix.stackexchange.com/a/265151/20650
tidak berfungsi karena Anda mengarahkan stdin ke sesuatu yang tidak mempedulikannya, yaitu tugas
berfungsi, tetapi ada back-tic di sana yang dapat menghentikan Anda dari menggunakan ini. Juga, Anda harus benar-benar menghindari menggunakan backticks, lebih baik menggunakan notasi substitusi perintah
$(..)
.sumber
$(cat <<'END'
saja. @ Neil: Baris baru terakhir tidak akan menjadi bagian dari variabel, tetapi sisanya akan dipertahankan.echo "$A"
(yaitu menempatkan $ A dalam tanda kutip ganda) dan Anda memang melihat baris baru!REM=<< 'REM' ... comment block goes here ... REM
. Atau lebih kompak: << 'REM' ...
,. Di mana "REM" dapat berupa "CATATAN" atau "SCRATCHPAD", dll.Ini tidak benar - Anda mungkin hanya disesatkan oleh perilaku gema:
echo $VAR # strips newlines
echo "$VAR" # preserves newlines
sumber
Bercabang dari jawaban Neil , Anda sering tidak membutuhkan var sama sekali, Anda dapat menggunakan fungsi dengan cara yang sama seperti variabel dan itu jauh lebih mudah dibaca daripada solusi inline atau
read
-berbasis.sumber
Array adalah variabel, jadi dalam hal ini mapfile akan berfungsi
Maka Anda bisa mencetak seperti ini
sumber
menetapkan nilai heredoc ke variabel
digunakan sebagai argumen dari suatu perintah
sumber
echo "$VAR"
Saya menemukan diri saya harus membaca string dengan NULL di dalamnya, jadi di sini adalah solusi yang akan membaca apa pun yang Anda lemparkan padanya. Meskipun jika Anda benar-benar berurusan dengan NULL, Anda harus menghadapinya pada level hex.
$ cat> read.dd.sh
Bukti:
Contoh HEREDOC (dengan ^ J, ^ M, ^ I):
sumber
Berkat jawaban dimo414 , ini menunjukkan bagaimana solusi hebatnya bekerja, dan menunjukkan bahwa Anda dapat dengan mudah mengutip dan variabel dalam teks:
contoh output
test.sh
sumber
sumber