Come specificare una variabile di shell multilinea?


122

Ho scritto una domanda:

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

sql locale: una stringa molto lunga. La query non è formattata. Come posso dividere una stringa in più righe?


4
Di cosa shellsi parla bene qui? Dovresti batchessere basho sei davvero dal lato oscuro?
Chris Seymour

1
se questo è shell / bash, non dovresti circondare =con spazi.
Nik O'Lai

Risposte:


138

Utilizzare readcon un heredoc come mostrato di seguito:

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

echo "$sql"

52
Nota che readavrà un codice di uscita di 1 in questa situazione; se questo è importante ( set -ead esempio, stai correndo con ), ti consigliamo di aggiungere un || truealla fine della prima riga.
chepner

4
set -eesce dalla shell se un comando ha uno stato di uscita "imprevisto" diverso da zero. Con "imprevisto", intendo che viene eseguito in un contesto in cui non stai osservando specificamente il suo stato di uscita. falseda solo, ad esempio, uscirebbe dalla shell. false || trueno, dal momento che stai anticipando lo stato di uscita diverso da zero specificando un altro comando da eseguire se il primo fallisce.
chepner

1
Il problema con set -e e read (vedi ultimo esercizio) è descritto qui in dettaglio: mywiki.wooledge.org/BashFAQ/105
Niklas Peter

5
cosa ci -d ' 'fa qui?
hg_git

3
@hg_git Dicendo di readnon interrompere la lettura quando si incontra una nuova riga.
Cyker

171

è sufficiente inserire una nuova riga dove necessario

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

shell cercherà le virgolette di chiusura


7
non è una buona soluzione se la query sql contiene virgolette doppie. Dovrai sfuggirgli e diventerà disordinato.
dogbane

13
Le doppie virgolette @dogbane appaiono raramente nella maggior parte dei dialetti SQL, quindi in pratica questo è pulito.
Iain Samuel McLean Elder

4
Quindi racchiudi la stringa tra virgolette singole.
tripleee

Non sono sicuro del motivo per cui desideri o hai bisogno dell'interruzione di riga principale. Per la mia domanda non l'ho fatto, quindi ho iniziato consql="SELECT c2, c2
bhfailor

1
Buffo che sembri troppo facile per essere vero. Cordiali saluti, per aggiungere DQ, basta creare una variabile DQ = '\ "' e quindi fare riferimento nell'istruzione con $ {DQ}.
Timothy C. Quinn,

69

Vorrei dare un'ulteriore risposta, mentre le altre saranno sufficienti nella maggior parte dei casi.

Volevo scrivere una stringa su più righe, ma il suo contenuto doveva essere una riga singola.

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

Mi dispiace se questo è un po 'fuori tema (non ne avevo bisogno per SQL). Tuttavia, questo post compare tra i primi risultati quando si cercano variabili di shell multilinea e una risposta aggiuntiva sembrava appropriata.


1
Anche senza il mio contenuto esce su una riga.
papiro

12
@papiro, prova echo "$sql"invece di echo $sql.
Michael Mol

@MichaelMol - Circa due decenni dopo la mia prima installazione di Linux e imparo ancora qualcosa di nuovo. Grazie per questo "trucco".
Seth

6

Grazie alla risposta di dimo414 a una domanda simile , questo mostra come funziona la sua ottima soluzione e mostra che puoi anche avere citazioni e variabili nel testo facilmente:

output di esempio

$ ./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

5

readnon esporta la variabile (che è una buona cosa la maggior parte delle volte). Ecco un'alternativa che può essere esportata in un comando, può preservare o scartare gli avanzamenti di riga e consente di mescolare gli stili di citazione secondo necessità. Funziona per bash e zsh.

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

Ammetto che la necessità di citazioni lo renda brutto per SQL, ma risponde alla domanda (più generalmente espressa) nel titolo.

Lo uso in questo modo

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')

in un file proveniente da my .bashrce .zshrc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.