Wie gebe ich eine mehrzeilige Shell-Variable an?


122

Ich habe eine Anfrage geschrieben:

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

local sql - eine sehr lange Zeichenfolge. Die Abfrage ist nicht formatiert. Wie kann ich eine Zeichenfolge in mehrere Zeilen aufteilen?


4
Was shellspricht hier gut? Sollte batchsein bashoder sind Sie wirklich von der dunklen Seite ?
Chris Seymour

1
Wenn dies Shell / Bash ist, sollten Sie nicht =mit Leerzeichen umgeben.
Nik O'Lai

Antworten:


138

Verwenden Sie readmit einem Heredoc wie unten gezeigt:

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

echo "$sql"

52
Beachten Sie, dass readin dieser Situation der Exit-Code 1 angezeigt wird. Wenn dies wichtig ist ( set -ez. B. mit dem Sie arbeiten), möchten Sie || trueam Ende der ersten Zeile ein hinzufügen .
Chepper

4
set -eBeendet die Shell, wenn ein Befehl einen "unerwarteten" Exit-Status ungleich Null hat. Mit "unerwartet" meine ich, dass es in einem Kontext ausgeführt wird, in dem Sie den Exit-Status nicht speziell betrachten. falsevon sich aus würde zum Beispiel die Shell verlassen.false || truewürde nicht, da Sie den Exit-Status ungleich Null antizipieren, indem Sie einen anderen Befehl angeben, der ausgeführt werden soll, wenn der erste fehlschlägt.
Chepner

1
Das Problem mit set -e und read (siehe letzte Übung) wird hier ausführlich beschrieben: mywiki.wooledge.org/BashFAQ/105
Niklas Peter

5
was macht -d ' 'hier
hg_git

3
@hg_git Sagt, dass Sie readnicht aufhören sollen zu lesen, wenn Sie auf eine neue Zeile stoßen.
Cyker

170

Fügen Sie bei Bedarf einfach eine neue Zeile ein

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

Shell sucht nach dem schließenden Anführungszeichen


7
Keine gute Lösung, wenn die SQL-Abfrage doppelte Anführungszeichen enthält. Sie müssen ihnen entkommen und es wird chaotisch.
Dogbane

13
@dogbane Doppelzitate kommen in den meisten SQL-Dialekten selten vor, daher ist dies in der Praxis sauber.
Iain Samuel McLean Elder

4
Wickeln Sie dann die Zeichenfolge in einfache Anführungszeichen.
Tripleee

Ich bin mir nicht sicher, warum Sie den Zeilenumbruch wünschen oder brauchen. Für meine Bewerbung habe ich nicht so habe ich gerade angefangen mitsql="SELECT c2, c2
bhfailor

1
Komisch, dass es zu einfach scheint, wahr zu sein. Zu Ihrer Information, um DQ hinzuzufügen, erstellen Sie einfach eine Variable DQ = '\ "' und verweisen Sie dann in der Anweisung mit $ {DQ}.
Timothy C. Quinn

69

Ich möchte eine zusätzliche Antwort geben, während die anderen in den meisten Fällen ausreichen werden.

Ich wollte einen String über mehrere Zeilen schreiben, aber sein Inhalt musste einzeilig sein.

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

Es tut mir leid, wenn dies etwas vom Thema abweicht (ich brauchte dies nicht für SQL). Dieser Beitrag gehört jedoch zu den ersten Ergebnissen bei der Suche nach mehrzeiligen Shell-Variablen, und eine zusätzliche Antwort erschien angemessen.


1
Auch ohne das \ 's kommt mein Inhalt in einer Zeile heraus.
Papiro

12
@papiro, versuche echo "$sql"statt echo $sql.
Michael Mol

@MichaelMol - Ungefähr zwei Jahrzehnte nach meiner ersten Linux-Installation lerne ich immer noch etwas Neues. Danke für diesen "Trick".
Seth

6

Dank der Antwort von dimo414 auf eine ähnliche Frage zeigt dies, wie seine großartige Lösung funktioniert, und zeigt, dass Sie auch leicht Anführungszeichen und Variablen im Text haben können:

Beispielausgabe

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

readexportiert die Variable nicht (was die meiste Zeit gut ist). Hier ist eine Alternative, die in einem Befehl exportiert werden kann, Zeilenvorschübe beibehalten oder verwerfen kann und das Mischen von Anführungszeichenstilen nach Bedarf ermöglicht. Funktioniert für Bash und Zsh.

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

Ich gebe zu, dass die Notwendigkeit des Zitierens dies für SQL hässlich macht, aber es beantwortet die (allgemeiner ausgedrückt) Frage im Titel.

Ich benutze es so

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 einer Datei von meiner .bashrcund .zshrc.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.