Как использовать перенос строки в команде read -p при использовании переменных в строке приглашения

Как использовать перенос строки в команде read -p при использовании переменных в строке приглашения

Я хочу, чтобы после приглашения был перенос строки при использовании функции cowsay в приглашении:

read -p "$(cowsay "do you know this word?") \n" answer

есть несколько ответов на эту проблему:

1)https://stackoverflow.com/questions/4296108/how-do-i-add-a-line-break-for-read-command/4296147

2)https://stackoverflow.com/questions/12741529/how-to-break-a-line-add-a-newline-in-read-p-in-bash

Однако в ответах используется ''обозначение, которое не разрешает cowsayкоманду

решение1

Зачем вам использовать -pопцию, для которой вам понадобится bashоболочка?

Просто делать:

cowsay "do you know this word?"
read answer

В bash, эта -pопция полезна только в сочетании с -e(другое bashрасширение, которое заставляет bash's readвести себя как zsh's vared), где bashможет потребоваться перерисовать приглашение в некоторых случаях (например, при Ctrl+L). Но тогда вам, вероятно, не понадобится и не захочется перерисовывать это приглашение, если оно состоит из нескольких строк.

Если бы вы захотели, вы всегда могли бы сделать:

read -ep "$(cowsay "do you know this word?")"$'\n' answer

$'...'(здесь используется форма цитирования ksh93 , которая понимает управляющие последовательности в стиле C)

или

read -ep "$(cowsay "do you know this word?")
" answer

В более общем плане проблема заключается в том, что подстановка команд удаляет символы новой строки (не один, а все, что можно считать ошибкой/неправильной функцией¹) из конца вывода команды.

Чтобы обойти это, обычный трюк заключается в следующем:

output=$(cowsay "do you know this word?"; echo .)
output=${output%.}
read -p "$output" answer

То есть, добавить .\nк выводу. Подстановка команды удаляет \n, а мы удаляем , .оставляя ${output%.}весь вывод команды (при условии, что он не содержит символов NUL в оболочках, отличных от zsh, и что это допустимый текст в текущей локали в yash).

Для справки, в других оболочках типа Korn синтаксис для readвыдачи приглашения сам по себе выглядит следующим образом:

read 'answer?prompt: '

Оболочка Korn также перерисовывала бы это приглашение при чтении из терминала, и была бы включена опция редактора (например, с помощью set -o emacsили set -o vi). zshтакже поддерживает этот синтаксис для совместимости, но редактор строк используется только для vared, а не для readthere.


¹ например, это делает такие вещи basename=$(basename -- "$file")неправильными, так как может удалить символы новой строки из конца имени файла, а не только те, которые добавленыbasename

Связанный контент