¿Cómo especificar una variable de shell de varias líneas?


122

He escrito una consulta:

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

sql local: una cadena muy larga. La consulta no tiene formato. ¿Cómo puedo dividir una cadena en varias líneas?


4
¿Qué shellestás hablando bien aquí? ¿Deberías batchser basho eres realmente del lado oscuro?
Chris Seymour

1
si es shell / bash, no debe rodear =con espacios.
Nik O'Lai

Respuestas:


138

Úselo readcon un heredoc como se muestra a continuación:

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

echo "$sql"

52
Tenga en cuenta que readtendrá un código de salida de 1 en esta situación; si eso importa (está ejecutando con set -e, por ejemplo), querrá agregar un || trueal final de la primera línea.
chepner

4
set -esale del shell si un comando tiene un estado de salida "no anticipado" distinto de cero. Por "no anticipado", me refiero a que se ejecuta en un contexto en el que no se está mirando específicamente su estado de salida. falsepor sí mismo, por ejemplo, saldría del shell. false || trueno lo haría, ya que está anticipando el estado de salida distinto de cero al especificar otro comando para ejecutar si el primero falla.
chepner

1
El problema con set -e y read (ver último ejercicio) se describe aquí en detalle: mywiki.wooledge.org/BashFAQ/105
Niklas Peter

5
que hace -d ' 'aqui
hg_git

3
@hg_git Decir que readno deje de leer cuando se encuentre con una nueva línea.
Cyker

171

simplemente inserte una nueva línea donde sea necesario

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

shell buscará las comillas de cierre


7
no es una buena solución si la consulta SQL contiene comillas dobles. Tendrás que escapar de ellos y se complicará.
dogbane

13
Las comillas dobles de @dogbane rara vez aparecen en la mayoría de los dialectos SQL, por lo que en la práctica esto es limpio.
Iain Samuel McLean Elder

4
Luego, envuelva la cadena entre comillas simples.
tripleee

No estoy seguro de por qué quiere o necesita el salto de línea principal. Para mi aplicación no lo hice, así que acabo de comenzar consql="SELECT c2, c2
bhfailor

1
Es curioso que parezca demasiado fácil para ser verdad. FYI, para agregar DQ, simplemente cree una variable DQ = '\ "' y luego haga referencia a ella en la declaración con $ {DQ}.
Timothy C. Quinn

69

Me gustaría dar una respuesta adicional, mientras que las otras serán suficientes en la mayoría de los casos.

Quería escribir una cadena en varias líneas, pero su contenido tenía que ser de una sola línea.

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

Lo siento si esto es un poco fuera de tema (no lo necesitaba para SQL). Sin embargo, esta publicación aparece entre los primeros resultados al buscar variables de shell de múltiples líneas y una respuesta adicional parecía apropiada.


1
Incluso sin el \ 's, mi contenido se publica en una sola línea.
Papiro

12
@papiro, prueba en echo "$sql"lugar de echo $sql.
Michael Mol

@MichaelMol - Aproximadamente dos décadas después de mi primera instalación de Linux y todavía aprendo algo nuevo. Gracias por este "truco".
Seth

6

Gracias a la respuesta de dimo414 a una pregunta similar , esto muestra cómo funciona su gran solución y muestra que también puede tener citas y variables en el texto fácilmente:

salida de ejemplo

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

readno exporta la variable (lo cual es bueno la mayor parte del tiempo). Aquí hay una alternativa que se puede exportar en un comando, puede preservar o descartar los avances de línea y permite mezclar estilos de comillas según sea necesario. Funciona para bash y zsh.

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

Admito que la necesidad de citar hace que esto sea desagradable para SQL, pero responde a la pregunta (expresada de manera más general) en el título.

Lo uso así

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

en un archivo procedente de mi .bashrcy .zshrc.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.