Как вывести многострочную строку в Bash?

Как я могу вывести многострочную строку в Bash без использования нескольких эхо-вызовов, например, так:

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

Я ищу портативный способ сделать это, используя только встроенные функции Bash.

Ответ 1

Здесь документы часто используются для этой цели.

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

Report bugs to: 
up home page:
EOF

Они поддерживаются во всех производных от Bourne оболочек, включая все версии Bash.

Ответ 2

или вы можете сделать это:

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

Report bugs to: 
up home page: "

Ответ 3

Так как я рекомендовал printf в комментарии, я должен, вероятно, привести некоторые примеры его использования (хотя для печати сообщения об использовании я с большей вероятностью воспользуюсь ответами Денниса или Криса). printf немного сложнее в использовании, чем echo. Его первым аргументом является строка формата, в которой escape-последовательности (например, \n) всегда интерпретируются; он также может содержать директивы формата, начиная с %, которые определяют, где и как любые дополнительные аргументы включены в него. Вот два разных подхода к использованию для сообщения об использовании:

Сначала вы можете включить все сообщение в строку формата:

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

Обратите внимание, что в отличие от echo, вы должны явно указать окончательную новую строку. Кроме того, если сообщение содержит какие-либо символы %, они должны быть записаны как %%. Если вы хотите включить адреса bugreport и домашнюю страницу, их можно добавить совершенно естественно:

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: "

С помощью этой опции добавление адресов bugreport и домашней страницы довольно очевидно:

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

Ответ 4

Используйте параметр -e, затем вы можете напечатать новый символ строки с \n в строке.

Пример (но не уверен, хороший или нет)

Самое интересное, что опция -e не документирована в странице руководства MacOS, пока она еще доступна. Он задокументирован на странице Linux.

Ответ 5

Вдохновленный проницательными ответами на этой странице, я создал смешанный подход, который я считаю самым простым и более гибким. Как вы думаете?

Во-первых, я определяю использование в переменной, что позволяет мне использовать его в разных контекстах. Формат очень прост, почти WYSIWYG, без необходимости добавлять какие-либо управляющие символы. Это кажется мне достаточно портативным (я запускал его на 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}"}

Ответ 6

Также с исходным кодом с отступом вы можете использовать <<- (с завершающей чертой), чтобы игнорировать начальные вкладки (но не начальные пробелы). Например это:

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

Выводит текст с отступом без пробела:

line1
line2