336

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

echo "usage: up [--level <n>| -n <levels>][--help][--version]"
echo 
echo "Report bugs to: "
echo "up home page: "

我正在寻找一种可移植的方式来做到这一点,只使用 Bash 内置。

4

11 回答 11

402

此处的文档通常用于此目的。

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

Report bugs to: 
up home page:
EOF

所有 Bourne 衍生的 shell 都支持它们,包括所有版本的 Bash。

于 2012-06-10T17:11:44.580 回答
224

或者你可以这样做:

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

Report bugs to: 
up home page: "
于 2012-06-10T15:33:07.803 回答
84

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

首先,我在一个变量中定义了用法,这允许我在不同的上下文中重用它。格式非常简单,几乎所见即所得,无需添加任何控制字符。这对我来说似乎相当便携(我在 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
"

然后我可以简单地将它用作

echo "$__usage"

甚至更好的是,在解析参数时,我可以在其中以单行方式回显它:

levelN=${2:?"--level: n is required!""${__usage}"}
于 2018-08-18T18:47:54.790 回答
39

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

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

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

于 2012-06-10T15:29:20.073 回答
25

由于我printf在评论中推荐过,我可能应该给出一些它的用法示例(尽管为了打印使用信息,我更有可能使用 Dennis 或 Chris 的答案)。 printf使用起来比echo. 它的第一个参数是一个格式字符串,其中总是解释转义符(如\n) ;它还可以包含以 开头的格式指令,这些指令控制在其中包含任何附加参数的位置和方式。以下是将其用于使用消息的两种不同方法:%

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

printf "usage: up [--level <n>| -n <levels>][--help][--version]\n\nReport bugs to: \nup home page: \n"

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

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

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

printf "%s\n" "usage: up [--level <n>| -n <levels>][--help][--version]" "" "Report bugs to: " "up home page: "

使用此选项,添加错误报告和主页地址非常明显:

printf "%s\n" "usage: up [--level <n>| -n <levels>][--help][--version]" "" "Report bugs to: $bugreport" "up home page: $homepage"
于 2012-06-10T23:47:51.557 回答
17

此外,对于缩进的源代码,您可以使用<<-(带有尾随破折号)忽略前导制表符(但不是前导空格)。

例如这个:

if [ some test ]; then
    cat <<- xx
        line1
        line2
xx
fi

输出没有前导空格的缩进文本:

line1
line2
于 2018-03-01T11:31:49.957 回答
12

我通常使用我认为更灵活和直观的内置读取命令。它将一行的内容读入一个变量,并允许与特殊的 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"
于 2021-04-19T21:08:54.263 回答
10

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

echo -e "This will generate a next line \nThis new line is the result"
于 2020-11-15T14:56:02.663 回答
2

还有一件事,使用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"

此 ^^^ 将打印整个消息,其中插入了其他变量,而不是%s按提供的顺序。

于 2021-01-19T09:49:08.347 回答
0
    You can write your
    text
        freely,
                   in a separate: 
                             ----file.

接着

echo "$(</pathto/your_multiline_file)"
于 2021-11-10T12:07:36.737 回答
0

做这个:

dedent() {
    local -n reference="$1"
    reference="$(echo "$reference" | sed 's/^[[:space:]]*//')"
}

text="this is line one
      this is line two
      this is line three\n"

# `text` is passed by reference and gets dedented
dedent text

printf "$text"

输出不先调用dedent

this is line one
      this is line two
      this is line three

...并首先调用 WITH dedent(如上所示):

this is line one
this is line two
this is line three

有关完整的解释,请参阅我已经写过的地方:

  1. 等效于 bash 中的 python 的 textwrap dedent
  2. 带有额外空格的多行字符串(保留缩进)

当然,感谢@Andreas Louv 在这里向我展示了sed该功能的一部分

于 2022-02-18T08:14:12.950 回答