Как указать многострочную переменную оболочки?


123

Я написал запрос:

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

local sql - очень длинная строка. Запрос не отформатирован. Как разбить строку на несколько строк?


4
Что shellтут хорошо говорят? Должно batchбыть bashили ты действительно из темной стороны?
Крис Сеймур

1
если это оболочка / bash, не следует окружать =пробелами.
Nik O'Lai

Ответы:


139

Используйте readс heredoc, как показано ниже:

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

echo "$sql"

52
Обратите внимание, что readв этой ситуации будет код выхода 1; если это имеет значение (например, вы работаете с set -e), вам нужно добавить || trueв конец первой строки.
chepner

4
set -eвыходит из оболочки, если команда имеет "непредвиденный" ненулевой статус выхода. Под «непредвиденным» я подразумеваю, что он работает в контексте, в котором вы специально не смотрите на его статус выхода. falseсам по себе, например, выйдет из оболочки. false || trueне будет, так как вы ожидаете ненулевого статуса выхода, указав другую команду, которая будет запускаться в случае сбоя первой.
chepner

1
Проблема с set -e и read (см. Последнее упражнение) подробно описана здесь: mywiki.wooledge.org/BashFAQ/105
Никлас Питер

5
что -d ' 'здесь делает?
hg_git

3
@hg_git Указание readне прекращать чтение при обнаружении новой строки.
Cyker

172

просто вставьте новую строку там, где это необходимо

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

оболочка будет искать закрывающую кавычку


7
не лучшее решение, если запрос sql содержит двойные кавычки. Вам придется сбежать от них, и это станет беспорядком.
dogbane

13
Двойные кавычки @dogbane редко встречаются в большинстве диалектов SQL, так что на практике это чисто.
Iain Samuel McLean Elder

4
Затем заключите строку в одинарные кавычки.
tripleee

Не уверен, зачем вам нужен перенос ведущей строки. Для моего приложения я этого не сделал, поэтому я просто начал сsql="SELECT c2, c2
bhfailor

1
Забавно, что это кажется слишком легким, чтобы быть правдой. К вашему сведению, чтобы добавить DQ, просто создайте переменную DQ = '\ "', а затем укажите ее в инструкции с помощью $ {DQ}.
Тимоти К. Куинн,

69

Я хотел бы дать еще один ответ, а другого в большинстве случаев будет достаточно.

Я хотел написать строку на нескольких строках, но ее содержимое должно было быть однострочным.

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

Прошу прощения, если это немного не по теме (мне это не нужно для SQL). Однако этот пост появляется среди первых результатов при поиске многострочных переменных оболочки, и дополнительный ответ казался подходящим.


1
Даже без \ 'мой контент выходит на одной строке.
papiro

12
@papiro, попробуйте echo "$sql"вместо echo $sql.
Майкл Мол

@MichaelMol - Примерно через два десятилетия после моей первой установки Linux я все еще узнаю что-то новое. Спасибо за эту «выходку».
Сет,

6

Благодаря ответу dimo414 на аналогичный вопрос , это показывает, как работает его отличное решение, и показывает, что вы также можете легко использовать кавычки и переменные в тексте:

пример вывода

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

readне экспортирует переменную (что в большинстве случаев хорошо). Вот альтернатива, которая может быть экспортирована одной командой, может сохранять или отбрасывать перевод строки и позволяет при необходимости смешивать стили цитирования. Работает на bash и zsh.

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

Я признаю, что необходимость цитирования делает это некрасивым для SQL, но он отвечает на (более широко выраженный) вопрос в заголовке.

Я использую это так

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

в файле, полученном как из моих, так .bashrcи из .zshrc.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.