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

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

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

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


person user2219963    schedule 15.03.2013    source источник
comment
Что shell здесь хорошо говорят? Должно batch быть bash или вы действительно из темной стороны?   -  person Chris Seymour    schedule 15.03.2013
comment
если это оболочка / bash, не следует окружать = пробелами.   -  person Nik O'Lai    schedule 15.03.2013


Ответы (5)


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

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

echo "$sql"
person dogbane    schedule 15.03.2013
comment
Обратите внимание, что в этой ситуации read будет иметь код выхода 1; если это важно (например, вы работаете с set -e), вам нужно добавить || true в конце первой строки. - person chepner; 15.03.2013
comment
@chepner, ты спас мне год облысения. как set -e на это влияет? просто любопытно. - person chakrit; 22.09.2015
comment
set -e выходит из оболочки, если команда имеет непредвиденный ненулевой статус выхода. Под непредвиденным я имею в виду, что он работает в контексте, в котором вы специально не смотрите на его статус выхода. false сам по себе, например, выйдет из оболочки. false || true не будет, так как вы ожидаете ненулевого статуса выхода, указав другую команду, которая будет выполняться в случае сбоя первой. - person chepner; 22.09.2015
comment
Проблема с set -e и read (см. Последнее упражнение) подробно описана здесь: mywiki.wooledge.org / BashFAQ / 105 - person Niklas Peter; 25.02.2016
comment
что здесь -d ' '? - person hg_git; 26.09.2016
comment
read -d кажется банальным, есть ли способ сделать это в стандартной оболочке? - person wilx; 10.10.2016
comment
@hg_git Указывает read не прекращать чтение при обнаружении новой строки. - person Cyker; 04.12.2016
comment
Вы должны использовать «EOF» в первой строке, если многострочная строка не предназначена для анализа на предмет переменных оболочки и т.п. - person Michael Mol; 03.05.2017

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

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

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

person Nik O'Lai    schedule 15.03.2013
comment
не лучшее решение, если запрос sql содержит двойные кавычки. Вам придется убегать от них, и все станет беспорядочно. - person dogbane; 15.03.2013
comment
Двойные кавычки @dogbane редко встречаются в большинстве диалектов SQL, так что на практике это чисто. - person Iain Samuel McLean Elder; 07.09.2014
comment
Затем заключите строку в одинарные кавычки. - person tripleee; 13.01.2016
comment
Не уверен, зачем вам нужен перенос ведущей строки. Для моего приложения я этого не сделал, поэтому я просто начал с sql="SELECT c2, c2 - person bhfailor; 30.01.2018
comment
Забавно, что это кажется слишком легким, чтобы быть правдой. К вашему сведению, чтобы добавить DQ, просто создайте переменную DQ = '\', а затем укажите на нее ссылку в операторе с помощью $ {DQ}. - person Timothy C. Quinn; 11.05.2019

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

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

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

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

person islijepcevic    schedule 22.05.2014
comment
Даже без \ мой контент выходит на одной строке. - person papiro; 30.06.2016
comment
@papiro, попробуйте echo "$sql" вместо echo $sql. - person Michael Mol; 03.05.2017
comment
@MichaelMol - Примерно через два десятилетия после моей первой установки Linux я все еще узнаю что-то новое. Спасибо за эту уловку. - person Seth; 04.12.2019

Благодаря ответу 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
person Brad Parks    schedule 22.02.2016

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.

person EndlosSchleife    schedule 18.10.2016