Як розбити довгу рядок на кілька рядків у запиті read -p у вихідному коді?


19

Я пишу інсталяційний сценарій, який буде виконуватися як /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 на 51 лінійному терміналі на моєму моніторі 1440p - відмінно підходить для підключення файлів журналів та редагування вихідного коду in vim) та 2. навчитися приймати Те, що іноді рядки вихідного коду будуть довші 80 символів - це неминуче. Якби я використовував менший шрифт, я міг би мати ще ширший термінал, але моє поточне налаштування - хороший компроміс між шириною та розбірливістю.
cas

Відповіді:


17

Перш за все, давайте роз'єднаємо прочитане з рядка тексту за допомогою змінної:

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

Таким чином проблема стає такою: як призначити два рядки змінній.

Звичайно, перша спроба зробити це:

a="line-1 \
line-2"

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

Але вам не подобається відсутність відступу, який це створює, ну, тоді ми можемо спробувати прочитати рядки у варі з here-doc (пам’ятайте, що для відступних рядків всередині тут-doc потрібна вкладка, а не пробіли, правильно працювати):

    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 Ми обоє згідні. Це причина подяки :-). Знову дякую.

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 символів на рядок у вихідному коді сценарію ! Дякую за відповідь, хоча :)
Матеуш Піотровський

Мені не подобається підхід, який ви запропонували, оскільки немає відступів. Якщо мій 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 зробив, я додав робочу версію того, що ви спочатку намагалися.
тердон

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.