Como especificar uma variável de shell com várias linhas?


122

Eu escrevi uma consulta:

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

sql local - uma string muito longa. A consulta não está formatada. Como posso dividir uma string em várias linhas?


4
O que shellestão falando bem aqui? Deveria batchser bashou você é realmente do lado sombrio?
Chris Seymour

1
se for shell / bash, você não deve envolver =espaços.
Nik O'Lai

Respostas:


138

Usar read com um heredoc, como mostrado abaixo:

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

echo "$sql"

52
Observe que readterá um código de saída 1 nessa situação; se isso importa (você está executando set -e, por exemplo), adicione um || trueno final da primeira linha.
chepner

4
set -esai do shell se um comando tiver um status de saída diferente de zero "não antecipado". Por "imprevisto", quero dizer que é executado em um contexto em que você não está olhando especificamente para o status de saída. falsepor si só, por exemplo, sairia do shell. false || truenão, pois você está antecipando o status de saída diferente de zero, especificando outro comando para executar se o primeiro falhar.
chepner

1
O problema com set -e e read (veja o último exercício) é descrito aqui em detalhes: mywiki.wooledge.org/BashFAQ/105
Niklas Peter

5
o que -d ' 'faz aqui?
Hg_git 26/09/16

3
@hg_git Dizendo readpara não parar de ler ao encontrar uma nova linha.
Cyker 04/12/16

170

basta inserir uma nova linha sempre que necessário

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

shell estará procurando as aspas finais


7
não é uma boa solução se a consulta sql contiver aspas duplas. Você terá que escapar deles e ficará confuso.
precisa

13
As aspas duplas do @dogbane aparecem raramente na maioria dos dialetos SQL; portanto, na prática, isso é limpo.
Iain Samuel McLean Elder

4
Em seguida, enrole a string entre aspas simples.
Tripleee

Não sabe por que deseja ou precisa da quebra de linha principal. Para o meu pedido eu não fiz, então eu apenas comecei comsql="SELECT c2, c2
bhfailor

1
Engraçado que parece fácil demais para ser verdade. FYI, para adicionar DQ, basta criar um DQ variável = '\ "' e, em seguida, fazer referência a ela na demonstração com $ {DQ}.
Timothy C. Quinn

69

Eu gostaria de dar uma resposta adicional, enquanto as outras serão suficientes na maioria dos casos.

Eu queria escrever uma string em várias linhas, mas seu conteúdo precisava ser de linha única.

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

Sinto muito se isso estiver um pouco fora do tópico (eu não precisava disso para SQL). No entanto, este post aparece entre os primeiros resultados ao pesquisar variáveis ​​de shell de várias linhas e uma resposta adicional parecia apropriada.


1
Mesmo sem o meu conteúdo está saindo em uma linha.
30616 papiro

12
@ papiro, tente em echo "$sql"vez de echo $sql.
Michael Mol

@MichaelMol - Cerca de duas décadas após a minha primeira instalação do Linux e eu ainda aprendo algo novo. Obrigado por este "truque".
Seth

6

Graças à resposta de dimo414 a uma pergunta semelhante , isso mostra como sua ótima solução funciona e mostra que você também pode ter aspas e variáveis ​​no texto:

saída de exemplo

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

readnão exporta a variável (o que é bom na maioria das vezes). Aqui está uma alternativa que pode ser exportada em um comando, pode preservar ou descartar alimentações de linha e permite misturar estilos de aspas, conforme necessário. Funciona para o bash e o zsh.

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

Admito que a necessidade de citar torna isso feio para o SQL, mas responde à pergunta (mais geralmente expressa) no título.

Eu uso assim

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

em um arquivo originado tanto do meu .bashrccomo do .zshrc.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.