Bagaimana cara menentukan variabel shell multi-baris?

122

Saya telah menulis pertanyaan:

function print_ui_hosts
{
local sql = "select ........."
print_sql "$ sql"
}

sql lokal - string yang sangat panjang. Kueri belum diformat. Bagaimana cara membagi string menjadi beberapa baris?

pengguna2219963
sumber
4
Apa shellyang dibicarakan baik-baik di sini? Harus batchmenjadi bashatau Anda benar-benar dari darkside tersebut?
Chris Seymour
1
jika ini adalah shell / bash, Anda tidak boleh =menggunakan spasi.
Nik O'Lai

Jawaban:

138

Gunakan readdengan heredoc seperti yang ditunjukkan di bawah ini:

read -d '' sql << EOF
select c1, c2 from foo
where c1='something'
EOF

echo "$sql"
dogbane
sumber
52
Perhatikan bahwa readakan memiliki kode keluar 1 dalam situasi ini; jika itu penting (Anda menjalankan set -e, misalnya), Anda akan ingin menambahkan a || truedi akhir baris pertama.
chepner
4
set -ekeluar dari shell jika perintah memiliki status keluar bukan-nol yang "tidak diantisipasi". Dengan "tak terduga", maksud saya ini berjalan dalam konteks di mana Anda tidak secara khusus melihat status keluarnya. falsedengan sendirinya, misalnya, akan keluar dari shell. false || truetidak akan, karena Anda mengantisipasi status keluar bukan-nol dengan menentukan perintah lain untuk dijalankan jika yang pertama gagal.
chepner
1
Masalah dengan set -e dan baca (lihat latihan terakhir) dijelaskan di sini secara rinci: mywiki.wooledge.org/BashFAQ/105
Niklas Peter
5
apa yang -d ' 'dilakukan disini?
hg_git
3
@hg_git Memberi readtahu untuk tidak berhenti membaca saat menemukan baris baru.
Cyker
171

cukup masukkan baris baru jika perlu

sql="
SELECT c1, c2
from Table1, Table2
where ...
"

shell akan mencari tanda kutip penutup

Nik O'Lai
sumber
7
bukan solusi yang baik jika kueri sql berisi tanda kutip ganda. Anda harus melarikan diri dari mereka dan itu akan menjadi berantakan.
dogbane
13
Kutipan ganda @dogbane jarang muncul di sebagian besar dialek SQL, jadi dalam praktiknya ini bersih.
Iain Samuel McLean Elder
4
Kemudian bungkus string dalam tanda kutip tunggal.
tripleee
Tidak yakin mengapa Anda menginginkan atau membutuhkan jeda baris terdepan. Untuk aplikasi saya, saya tidak melakukannya, jadi saya baru mulai dengansql="SELECT c2, c2
bhfailor
1
Lucu karena tampaknya terlalu mudah untuk menjadi kenyataan. FYI, untuk menambahkan DQ, buat saja variabel DQ = '\ "' dan kemudian referensikan dalam pernyataan dengan $ {DQ}.
Timothy C. Quinn
69

Saya ingin memberikan satu jawaban tambahan, sementara yang lain sudah cukup dalam banyak kasus.

Saya ingin menulis string di beberapa baris, tetapi isinya harus satu baris.

sql="                       \
SELECT c1, c2               \
from Table1, ${TABLE2}      \
where ...                   \
"

Saya minta maaf jika ini sedikit di luar topik (saya tidak membutuhkan ini untuk SQL). Namun, posting ini muncul di antara hasil pertama saat mencari variabel shell multi-baris dan jawaban tambahan sepertinya sesuai.

islijepcevic.dll
sumber
1
Bahkan tanpa \ 's konten saya keluar di satu baris.
papiro
12
@papiro, coba echo "$sql"alih-alih echo $sql.
Michael Mol
@MichaelMol - Sekitar dua dekade setelah instalasi Linux pertama saya dan saya masih belajar sesuatu yang baru. Terima kasih untuk "trik" ini.
Seth
6

Berkat jawaban dimo414 untuk pertanyaan serupa , ini menunjukkan bagaimana solusi hebatnya bekerja, dan menunjukkan bahwa Anda juga dapat memiliki kutipan dan variabel dalam teks dengan mudah:

contoh keluaran

$ ./test.sh

The text from the example function is:
  Welcome dev: Would you "like" to know how many 'files' there are in /tmp?

  There are "      38" files in /tmp, according to the "wc" command

test.sh

#!/bin/bash

function text1()
{
  COUNT=$(\ls /tmp | wc -l)
cat <<EOF

  $1 Would you "like" to know how many 'files' there are in /tmp?

  There are "$COUNT" files in /tmp, according to the "wc" command

EOF
}

function main()
{
  OUT=$(text1 "Welcome dev:")
  echo "The text from the example function is: $OUT"
}

main
Brad Parks
sumber
5

readtidak mengekspor variabel (yang sering kali merupakan hal yang baik). Berikut adalah alternatif yang dapat diekspor dalam satu perintah, dapat mempertahankan atau membuang umpan baris, dan memungkinkan pencampuran gaya kutipan sesuai kebutuhan. Bekerja untuk bash dan zsh.

oneLine=$(printf %s \
    a   \
    " b "   \
    $'\tc\t'    \
    'd '    \
)
multiLine=$(printf '%s\n' \
    a   \
    " b "   \
    $'\tc\t'    \
    'd '    \
)

Saya akui kebutuhan untuk mengutip membuat ini jelek untuk SQL, tetapi itu menjawab pertanyaan (yang lebih umum diungkapkan) dalam judul.

Saya menggunakannya seperti ini

export LS_COLORS=$(printf %s    \
    ':*rc=36:*.ini=36:*.inf=36:*.cfg=36:*~=33:*.bak=33:*$=33'   \
    ...
    ':bd=40;33;1:cd=40;33;1:or=1;31:mi=31:ex=00')

dalam file yang bersumber dari my .bashrcdan .zshrc.

EndlosSchleife
sumber