Как разбить длинную строку на несколько строк в приглашении чтения -p в исходном коде?


18

Я пишу сценарий установки, который будет запускаться как /bin/sh.

Есть строка, подсказывающая файл:

read -p "goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n] " REPLY

Я хотел бы разбить эту длинную строку на несколько строк, чтобы ни один из них не превышал 80 символов. Я говорю о строках в исходном коде скрипта; не о строках, которые должны быть напечатаны на экране при выполнении скрипта!

Что я пробовал:

  • Фрист подход:

    read -p "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] " REPLY

    Это не работает, так как не печатает Would you like to add this feature? [Y|n].

  • Второй подход:

    echo "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] "
    read REPLY

    Не работает так же. Он печатает новую строку после подсказки. Добавление -nопции echoне помогает: просто печатает:

    -n goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
  • Мой текущий обходной путь

    printf '%s %s ' \
        "goat can try change directory if cd fails to do so." \
        "Would you like to add this feature? [Y|n] "
    read REPLY

и мне интересно, есть ли лучший способ.

Помните, что я ищу /bin/shсовместимое решение.


1
Я предлагаю вам 1. использовать более широкий терминал и / или окно редактора (например, я использую 192-колоночный терминал размером 192 на моем мониторе 1440p - отлично подходит для отслеживания файлов журнала и редактирования исходного кода в vim) и 2. научиться принимать То, что иногда строки исходного кода будут длиннее 80 символов - это неизбежно. Если бы я использовал шрифт меньшего размера, у меня мог бы быть еще более широкий терминал, но моя текущая установка - хороший компромисс между шириной и удобочитаемостью.
Cas

Ответы:


16

Прежде всего, давайте отделим чтение от текстовой строки с помощью переменной:

text="line-1 line-2"             ### Just an example.
read -p "$text" REPLY

Таким образом, возникает проблема: как назначить две строки переменной.

Конечно, первая попытка сделать это, это:

a="line-1 \
line-2"

Написано так, что переменная aфактически получает значение line-1 line-2.

Но вам не нравится отсутствие отступов, которое это создает, ну, тогда мы можем попытаться прочитать строки в var из here-документа (имейте в виду, что строки с отступом внутри here-документа требуют табуляции, а не пробелов, работать правильно):

    a="$(cat <<-_set_a_variable_
        line-1
        line-2
        _set_a_variable_
    )"
echo "test1 <$a>"

Но это потерпит неудачу, так как на самом деле две строки записаны $a. Обходной путь для получения только одной строки может быть:

    a="$( echo $(cat <<-_set_a_variable_
        line 1
        line 2
        _set_a_variable_
        ) )"
echo "test2 <$a>"

Это близко, но создает другие дополнительные проблемы.

Правильное решение.

Все попытки, приведенные выше, просто сделают эту проблему более сложной, чем она должна быть.

Очень простой и простой подход:

a="line-1"
a="$a line-2"
read -p "$a" REPLY

Код для вашего конкретного примера (для любой оболочки, которая readподдерживает -p):

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        read -p "$a" REPLY

Для всех остальных оболочек используйте:

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        printf '%s' "$a"; read REPLY

@BinaryZebra, я знаю. Я просто исправил «для любой оболочки», так как не все оболочки читали и не все те, у кого есть -p.
Terdon

@terdon Мы оба согласны. Вот причина благодарности :-). Еще раз спасибо.

1

Обратная косая черта в конце строк допускает продолжение команды по нескольким строкам, а не фактические разрывы строк в выходных данных.

Таким образом, ваш первый подход, например, становится командой

read -p "goat can try change directory if cd fails to do so. " "Would you like to add this feature? [Y|n] " REPLY

Я не уверен, почему вы хотите читать, чтобы вывести несколько строк, но я бы просто использовал readдля строки подсказки и echoпредыдущей строки (ей).

Чтобы сделать код более читабельным в нескольких строках, не закрывайте и не открывайте кавычки между строками.

Попробуй это:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

Я не хочу, чтобы он напечатал две строки! Я просто хочу, чтобы в исходный код скрипта помещалось 80 символов на строку ! Спасибо за ответ, хотя :)
Mateusz Piotrowski

Мне не нравится подход, который вы предложили, потому что нет отступа. Если my readимеет отступ внутри функции, то ваш подход может испортить читабельность.
Матеуш Пиотровски

1

Я считаю, что подход @ BinaryZebra, использующий переменную, будет чище, но вы также можете сделать это так, как пытались. Вам просто нужно сохранить разрывы строк внутри кавычек:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

Вы думаете, что добавление новых строк после каждой строки увеличит читабельность? Потому что я не искал способ вставить \nв мою подсказку. Я просто хотел разбить код на несколько строк, чтобы каждая строка имела длину не более 80 символов.
Матеуш Пиотровски

1
@MateuszPiotrowski о, это имеет больше смысла. Тогда мой ответ не очень полезен. Пожалуйста, отредактируйте свой вопрос и уточните, что вы хотите разделить код, а не вывод. Я сейчас на мобильном, но я посмотрю, смогу ли я придумать что-нибудь завтра.
Тердон

1
@MateuszPiotrowski сделано, я добавил рабочую версию того, что вы изначально пытались.
Terdon

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.