¿Cómo dividir una cadena larga en varias líneas en el mensaje de lectura -p dentro del código fuente?

18

Estoy escribiendo un script de instalación que se ejecutará como /bin/sh.

Hay una línea que solicita un archivo:

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

Me gustaría dividir esta larga línea en muchas líneas para que ninguna de ellas supere los 80 caracteres. Estoy hablando de las líneas dentro del código fuente del script; ¡no se trata de las líneas que realmente se imprimirán en la pantalla cuando se ejecute el script!

Lo que he intentado:

  • Primer enfoque:

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

    Esto no funciona ya que no se imprime Would you like to add this feature? [Y|n].

  • Segundo enfoque:

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

    No funciona tan bien Imprime una nueva línea después de la solicitud. Agregar -nopción a echono ayuda: solo imprime:

    -n goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
  • Mi solución actual es

    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

y me pregunto si hay una mejor manera

Recuerda que estoy buscando una /bin/shsolución compatible.

Mateusz Piotrowski
fuente
1
Le sugiero que 1. use un terminal más amplio y / o una ventana de editor (por ejemplo, uso un terminal de 192 columnas por 51 líneas en mi monitor 1440p, ideal para seguir archivos de registro y editar el código fuente en vim) y 2. aprender a aceptar el El hecho de que a veces las líneas del código fuente tengan más de 80 caracteres, es inevitable. Si usara una fuente más pequeña, podría tener un terminal aún más ancho, pero mi configuración actual es un buen compromiso entre el ancho y la legibilidad.
cas

Respuestas:

16

En primer lugar, desacoplemos la lectura de la línea de texto usando una variable:

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

De esta manera, el problema se convierte en: Cómo asignar dos líneas a una variable.

Por supuesto, un primer intento de hacer eso es:

a="line-1 \
line-2"

Escrito así, la var arealmente obtiene el valor line-1 line-2.

Pero no le gusta la falta de sangría que esto crea, bueno, entonces podemos intentar leer las líneas en la var desde un documento aquí (tenga en cuenta que las líneas sangradas dentro del documento aquí necesitan una pestaña, no espacios, para trabajar correctamente):

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

Pero eso fallaría ya que en realidad se escriben dos líneas $a. Una solución para obtener solo una línea podría ser:

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

Eso está cerca, pero crea otros problemas adicionales.

Solución correcta

Todos los intentos anteriores harán que este problema sea más complejo de lo necesario.

Un enfoque muy básico y simple es:

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

El código para su ejemplo específico es (para cualquier shell cuyos readsoportes -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

Para todos los demás depósitos, use:

#!/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

fuente
@BinaryZebra lo sé. Acabo de corregir el "para cualquier shell" ya que no todos los shells han leído y no todos los que tienen -p.
terdon
@terdon Ambos estamos de acuerdo. Esa es la razón del agradecimiento :-). Gracias de nuevo.
1

La barra diagonal inversa al final de las líneas permite la continuación del comando en varias líneas, no en los saltos de línea reales en la salida.

Entonces, su primer enfoque, por ejemplo, se convierte en el comando

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

No estoy seguro de por qué quiere leer para generar varias líneas, pero simplemente lo usaría readpara la línea de solicitud y echolas líneas anteriores.

Para que el código sea más legible en varias líneas, no cierre / abra sus comillas entre líneas.

Prueba esto:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY
Ian Petts
fuente
¡No quiero que imprima dos líneas! ¡Solo quiero que el código se ajuste a 80 caracteres por línea en el código fuente del script ! Aunque gracias por la respuesta :)
Mateusz Piotrowski
No me gusta el enfoque que sugirió porque no hay sangría. Si my readestá sangrado dentro de una función, entonces su enfoque parece alterar la legibilidad.
Mateusz Piotrowski
1

Encuentro que el enfoque de @ BinaryZebra utiliza una variable para ser más limpio, pero también puede hacerlo de la manera que intentaba. Solo necesita mantener los saltos de línea dentro de las comillas:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY
terdon
fuente
¿Crees que agregar nuevas líneas después de cada línea aumentaría la legibilidad? Porque no estaba buscando la forma de insertar \nen mi solicitud. Solo quería dividir el código en varias líneas para que cada línea tenga como máximo 80 caracteres de longitud.
Mateusz Piotrowski
1
@MateuszPiotrowski oh, eso tiene mucho más sentido. Entonces mi respuesta no es muy útil. Edite su pregunta y aclare que desea dividir el código y no el resultado. Ahora estoy en el móvil, pero veré si puedo llegar a algo mañana.
terdon
1
@MateuszPiotrowski hecho, agregué una versión funcional de lo que estabas intentando originalmente.
terdon
0

¿Qué tal solo esto?

#! / bin / bash
leer -p "Hola
mundo
esto es un
multilínea
mensaje: "PROMPT
echo $ PROMPT

Desmond
fuente
¿Cómo lo sangras?
Mateusz Piotrowski