Comment spécifier une variable shell multiligne?


122

J'ai écrit une requête:

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

local sql - une très longue chaîne. La requête n'est pas formatée. Comment puis-je diviser une chaîne en plusieurs lignes?


4
De quoi shellparle bien ici? Devriez-vous batchêtre bashou êtes-vous vraiment du côté obscur?
Chris Seymour

1
s'il s'agit de shell / bash, vous ne devez pas entourer =d'espaces.
Nik O'Lai

Réponses:


138

Utiliser readavec un heredoc comme indiqué ci-dessous:

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

echo "$sql"

52
Notez qu'il readaura un code de sortie de 1 dans cette situation; si cela compte (vous exécutez avec set -e, par exemple), vous voudrez ajouter un || trueà la fin de la première ligne.
chepner

4
set -equitte le shell si une commande a un statut de sortie "imprévu" différent de zéro. Par "imprévu", je veux dire qu'il s'exécute dans un contexte où vous ne regardez pas spécifiquement son état de sortie. falsepar lui-même, par exemple, quitterait le shell. false || truene le ferait pas, puisque vous anticipez l'état de sortie différent de zéro en spécifiant une autre commande à exécuter si la première échoue.
chepner le

1
Le problème avec set -e et read (voir le dernier exercice) est décrit ici en détail: mywiki.wooledge.org/BashFAQ/105
Niklas Peter

5
que fait -d ' 'ici?
hg_git

3
@hg_git Dire de readne pas arrêter la lecture lorsque vous rencontrez une nouvelle ligne.
Cyker

171

insérez simplement une nouvelle ligne si nécessaire

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

shell recherchera le guillemet fermant


7
pas une bonne solution si la requête SQL contient des guillemets doubles. Vous devrez leur échapper et cela deviendra compliqué.
dogbane

13
Les guillemets doubles @dogbane apparaissent rarement dans la plupart des dialectes SQL, donc en pratique c'est clair.
Iain Samuel McLean Elder

4
Ensuite, mettez la chaîne entre guillemets simples.
tripleee

Je ne sais pas pourquoi vous voulez ou avez besoin du saut de ligne principal. Pour ma candidature, je ne l'ai pas fait alors je viens de commencer avecsql="SELECT c2, c2
bhfailor

1
C'est drôle que cela semble trop facile pour être vrai. Pour info, pour ajouter DQ, il suffit de créer une variable DQ = '\ "' puis de la référencer dans l'instruction avec $ {DQ}.
Timothy C. Quinn

69

Je voudrais donner une réponse supplémentaire, tandis que les autres suffiront dans la plupart des cas.

Je voulais écrire une chaîne sur plusieurs lignes, mais son contenu devait être sur une seule ligne.

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

Je suis désolé si cela était un peu hors sujet (je n'en avais pas besoin pour SQL). Cependant, cet article fait partie des premiers résultats lors de la recherche de variables shell multilignes et une réponse supplémentaire a semblé appropriée.


1
Même sans le \ 's, mon contenu sort sur une seule ligne.
papiro

12
@papiro, essayez echo "$sql"au lieu de echo $sql.
Michael Mol

@MichaelMol - Environ deux décennies après ma première installation de Linux et j'apprends encore quelque chose de nouveau. Merci pour ce "truc".
Seth

6

Merci à la réponse de dimo414 à une question similaire , cela montre comment fonctionne sa grande solution et montre que vous pouvez également avoir des guillemets et des variables dans le texte:

exemple de sortie

$ ./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'exporte pas la variable (ce qui est une bonne chose la plupart du temps). Voici une alternative qui peut être exportée en une seule commande, peut conserver ou ignorer les sauts de ligne et permet de mélanger les styles de guillemets selon les besoins. Fonctionne pour bash et zsh.

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

J'admets que le besoin de citations rend cela moche pour SQL, mais cela répond à la question (plus généralement exprimée) dans le titre.

Je l'utilise comme ça

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

dans un fichier provenant à la fois de mon .bashrcet de.zshrc .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.