如何在Bash中输出多行字符串?

hel*_*hod 218 bash

如何在不使用多个echo调用的情况下在Bash中输出多行字符串,如下所示:

echo "usage: up [--level <n>| -n <levels>][--help][--version]"
echo 
echo "Report bugs to: "
echo "up home page: "
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种可移植的方式,只使用Bash内置.

Pau*_*ce. 251

这里文件通常用于此目的.

cat << EOF
usage: up [--level <n>| -n <levels>][--help][--version]

Report bugs to: 
up home page:
EOF
Run Code Online (Sandbox Code Playgroud)

它们在所有Bourne派生的shell中都受支持,包括所有版本的Bash.

  • @MarkReed:这是真的,但它是[始终可用](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cat.html)(除非在特殊情况下). (8认同)
  • +1 Thx.我最终使用`read -d''help << - EOF ...`将多行字符串读入变量然后回显结果. (6认同)
  • 是的 - 但是`cat`不是内置的. (4认同)
  • 该死的天才,谢谢@DennisWilliamson!专业提示:如果您需要转义反引号等内容,您可以在第一行双引号分隔符,例如 `cat &lt;&lt; "EOF"`。 (3认同)
  • 我可以将HEREDOC保存到变量吗? (2认同)

小智 161

或者你可以这样做:

echo "usage: up [--level <n>| -n <levels>][--help][--version]

Report bugs to: 
up home page: "
Run Code Online (Sandbox Code Playgroud)

  • 如果您在函数中需要此功能不是很好,因为您要么需要1)将字符串一直缩到文件的左侧,要么2)使其缩进以与其余代码对齐,然后使用缩进 (4认同)
  • 作品。另请注意,如果您不想解释字符串,请使用 '(单引号)而不是 "(双引号)。如果您希望输出中包含 $something 或 `something` 而不是被替换。 (4认同)
  • @OliverWeiler:它甚至可以在 Dash 和 [Heirloom Bourne Shell](http://heirloom.sourceforge.net/sh.html) 等 Bourne shell 中工作。 (2认同)

Jor*_*rge 23

受到这个页面上富有洞察力的答案的启发,我创建了一种混合方法,我认为这种方法最简单,更灵活.你怎么看?

首先,我在变量中定义用法,这允许我在不同的上下文中重用它.格式非常简单,几乎所见即所得,无需添加任何控制字符.这对我来说似乎相当便携(我在MacOS和Ubuntu上运行它)

__usage="
Usage: $(basename $0) [OPTIONS]

Options:
  -l, --level <n>              Something something something level
  -n, --nnnnn <levels>         Something something something n
  -h, --help                   Something something something help
  -v, --version                Something something something version
"
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地使用它

echo "$__usage"
Run Code Online (Sandbox Code Playgroud)

甚至更好,在解析参数时,我可以在一个单行中回显它:

levelN=${2:?"--level: n is required!""${__usage}"}
Run Code Online (Sandbox Code Playgroud)

  • @Nicolas:在 `echo "$__usage"` 中使用双引号对我来说是必要的。`echo $__usage` 不起作用。 (4认同)
  • 这对我来说是一个脚本,上面的答案没有(没有修改). (3认同)
  • 这比包含一堆\ t和\ n的字符要干净得多,这些字符很难在文本中找到并进行扩展以使输出与脚本中的字符串大不相同。 (2认同)
  • 由于某些原因,它为我在同一行打印所有内容:/ (2认同)
  • 如果您使用 @jorge 的解决方案并发现所有内容都在同一行,请确保将变量括在引号中: ``` echo $__usage ``` 会将所有内容打印在一行上,而 ``` echo "$__usage " ``` 将保留换行符。 (2认同)

nha*_*tdh 22

使用-e选项,然后您可以\n在字符串中打印新行字符.

样品(但不确定是否好的)

有趣的是,该-e选项未在MacOS的手册页中记录,但仍可使用.它记录在Linux手册页中.

  • `echo -e`不可移植 - 例如,echo的某些实现将打印"-e"作为输出的一部分.如果您想要可移植性,请改用printf.例如,OS X 10.7.4上的/ bin/echo执行此操作.IIRC在10.5.0下,bash内置回声也很奇怪,但我不再记得细节了. (6认同)
  • 这些手册页用于系统提供的`echo`命令,`/ bin/echo`,在Mac OS上没有`-e`选项.当你在这些系统上使用bash时,它的内置`echo`命令会接管.您可以通过显式键入`/ bin/echo whatever`并观察行为差异来看到这一点.要查看内置文档,请键入"help echo". (4认同)
  • `echo -e`以前曾经咬过我...一定要使用`printf`或`cat`搭配heredoc。这里文档的`&lt;&lt;-`变体特别好,因为您可以删除输出中的前导缩进,但是可以缩进脚本中的可读性 (2认同)

Gor*_*son 21

自从我printf在评论中推荐以来,我应该举一些它的用法示例(虽然打印用法消息,我更有可能使用Dennis'或Chris'的答案). printf比使用起来有点复杂echo.它的第一个参数是一个格式字符串,其中escapes(like \n)总是被解释; 它还可以包含以...开头的格式指令%,它控制在其中包含任何其他参数的位置和方式.以下是将其用于使用消息的两种不同方法:

首先,您可以在格式字符串中包含整个消息:

printf "usage: up [--level <n>| -n <levels>][--help][--version]\n\nReport bugs to: \nup home page: \n"
Run Code Online (Sandbox Code Playgroud)

请注意,与之不同echo,您必须明确包含最终换行符.此外,如果消息恰好包含任何%字符,则必须将其写为%%.如果您想要包含bug报告和主页地址,可以很自然地添加它们:

printf "usage: up [--level <n>| -n <levels>][--help][--version]\n\nReport bugs to: %s\nup home page: %s\n" "$bugreport" "$homepage"
Run Code Online (Sandbox Code Playgroud)

其次,您可以使用格式字符串使其在单独的行上打印每个附加参数:

printf "%s\n" "usage: up [--level <n>| -n <levels>][--help][--version]" "" "Report bugs to: " "up home page: "
Run Code Online (Sandbox Code Playgroud)

使用此选项,添加bug报告和主页地址是相当明显的:

printf "%s\n" "usage: up [--level <n>| -n <levels>][--help][--version]" "" "Report bugs to: $bugreport" "up home page: $homepage"
Run Code Online (Sandbox Code Playgroud)


vic*_*lis 9

使用 -e 参数和转义字符 \n:

echo -e "This will generate a next line \nThis new line is the result"
Run Code Online (Sandbox Code Playgroud)


Zst*_*ack 8

我通常使用内置的 read 命令,我认为它更灵活和直观。它将一行的内容读入一个变量,并允许与特殊的 shell 变量 IFS 相关的分词。有关更多详细信息,请参阅此博客甚至手册页。

read -r -d '' usage <<-EOF
    usage: up [--level <n>| -n <levels>][--help][--version] 

    Report bugs to: $report server
    up home page: $HOME
EOF
echo "$usage"
Run Code Online (Sandbox Code Playgroud)

  • 最好的事情是“&lt;&lt;-”(带有减号)会忽略前导制表符,以便您可以在代码内缩进消息,而无需在打印时缩进。 (2认同)

Ell*_*iew 7

同样,对于缩进的源代码,您可以使用<<-(带短划线)忽略前导制表符(但不能忽略前导空格)。例如:

if [ some test ]; then
    cat <<- xx
        line1
        line2
xx
fi
Run Code Online (Sandbox Code Playgroud)

输出缩进的文本,不带前导空格:

line1
line2
Run Code Online (Sandbox Code Playgroud)


Iva*_*van 7

另一件事是,使用printf预定义变量(此处:)msg作为模板。

msg="First line %s
Second line %s
Third line %s
"

one='additional message for the first line'
two='2'
tri='this is the last one'

printf "$msg" "$one" "$two" "$tri"
Run Code Online (Sandbox Code Playgroud)

此 ^^^ 将打印整个消息,并插入附加变量,而不是%s按提供的顺序。