如何指定一个多行的Shell变量?

161

我已经写了一个查询:

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

本地 SQL - 一个非常长的字符串。查询未格式化。 如何将一个字符串拆分成多行?


4
我们谈论的是哪种“shell”?是应该将“batch”改为“bash”,还是你真的来自黑暗面? - Chris Seymour
2
如果这是shell/bash,你不应该在=周围加上空格。 - Nik O'Lai
5个回答

221

只需在必要的地方插入新行。

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

Shell 会寻找闭合引号。


14
如果 SQL 查询包含双引号,则这不是一个好的解决方案。你必须对它们进行转义,这会使情况变得混乱。 - dogbane
18
大多数 SQL 方言中很少出现双引号,因此在实践中这是干净的。 - Iain Samuel McLean Elder
6
将该字符串用单引号括起来。 - tripleee
不确定为什么您想要或需要前导换行符。对于我的应用程序,我没有这样做,所以我只是从 sql="SELECT c2, c2 开始。 - bhfailor
1
有趣的是,它看起来太简单以至于难以置信。顺便提一下,要添加DQ,只需创建一个变量DQ='"',然后在语句中使用${DQ}引用它。 - Timothy C. Quinn
显示剩余3条评论

184

使用以下示例中显示的heredoc与read一起使用:

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

echo "$sql"

68
请注意,在这种情况下,read命令的退出码是1;如果这很重要(例如,您正在使用set -e运行),则需要在第一行末尾添加|| true - chepner
4
如果命令的退出状态为“未预料”的非零值,set -e 将退出 shell。所谓“未预料”是指在不特别关注其退出状态的情况下运行。例如,单独使用 false 命令会导致 shell 退出。但是,在 false || true 中,由于您通过指定另一个要运行的命令来反应第一个命令失败的情况,因此不会退出。 - chepner
10
这里的 -d ' ' 是什么意思? - hg_git
6
告诉read函数在遇到换行符时不要停止读取。 - Cyker
3
如果多行字符串不打算解析为Shell变量等内容,则应在第一行使用“EOF”。 - Michael Mol
显示剩余3条评论

95

在大多数情况下,其他回答已经足够了,但我想再提供一个额外的答案。

我想将一个字符串分成多行编写,但其内容需要是单行。

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

如果这样说有点离题的话,我很抱歉(因为我不需要这个针对SQL)。但是,在搜索多行shell变量时,这篇文章出现在前几个结果中,补充一个答案似乎是合适的。


2
即使没有反斜杠,我的内容也会在一行上显示出来。 - papiro
23
尝试使用 echo "$sql" 而不是 echo $sql - Michael Mol
1
@MichaelMol -- 在我第一次安装Linux大约20年后,我仍然学到了新的东西。感谢您分享这个“技巧”。 - Seth

8

感谢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

6

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接