Come spezzare una lunga stringa in più righe nel prompt di read -p nel codice sorgente?


18

Sto scrivendo uno script di installazione che verrà eseguito come /bin/sh.

C'è una riga che richiede un file:

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

Vorrei spezzare questa lunga riga in molte righe in modo che nessuna di esse superi gli 80 caratteri. Sto parlando delle righe all'interno del codice sorgente dello script; non sulle linee che devono essere effettivamente stampate sullo schermo quando lo script viene eseguito!

Cosa ho provato:

  • Approccio frist:

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

    Questo non funziona poiché non stampa Would you like to add this feature? [Y|n].

  • Secondo approccio:

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

    Non funziona pure. Stampa una riga dopo il prompt. L'aggiunta -ndell'opzione a echonon aiuta: stampa solo:

    -n goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
  • La mia soluzione attuale è

    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

e mi chiedo se c'è un modo migliore.

Ricorda che sto cercando una /bin/shsoluzione compatibile.


1
Ti suggerisco di 1. utilizzare un terminale più ampio e / o una finestra dell'editor (ad es. Uso un terminale a 192 colonne per 51 linee sul mio monitor 1440p - ottimo per adattare i file di registro e modificare il codice sorgente in vim) e 2. imparare ad accettare il il fatto che a volte le righe del codice sorgente siano più lunghe di 80 caratteri - è inevitabile. Se avessi usato un font più piccolo, avrei potuto avere un terminale ancora più ampio ma la mia configurazione attuale è un buon compromesso tra larghezza e leggibilità.
Cas

Risposte:


16

Prima di tutto, separiamo la lettura dalla riga di testo usando una variabile:

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

In questo modo il problema diventa: come assegnare due righe a una variabile.

Naturalmente, un primo tentativo di farlo è:

a="line-1 \
line-2"

Scritto come tale, il var aottiene effettivamente il valore line-1 line-2.

Ma non ti piace la mancanza di rientro che questo crea, beh, allora potremmo provare a leggere le righe nel var da un here-doc (tieni presente che le righe rientrate all'interno del here-doc necessitano di una scheda, non di spazi, per funzionare correttamente):

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

Ma ciò fallirebbe poiché in realtà vengono scritte due righe $a. Una soluzione alternativa per ottenere solo una riga potrebbe essere:

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

Questo è vicino, ma crea altri problemi aggiuntivi.

Soluzione corretta.

Tutti i tentativi di cui sopra renderanno questo problema più complesso di quello che deve essere.

Un approccio molto semplice e di base è:

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

Il codice per il tuo esempio specifico è (per qualsiasi shell i cui readsupporti -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

Per tutte le altre shell, utilizzare:

#!/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 Lo so. Ho appena corretto "per qualsiasi shell" poiché non tutte le shell hanno letto e non tutte quelle che hanno -p.
terdon

@terdon Siamo entrambi d'accordo. Questo è il motivo del ringraziamento :-). Grazie ancora.

1

La barra rovesciata alla fine delle righe consente la continuazione del comando su più righe, non interruzioni di riga effettive nell'output.

Quindi il tuo primo approccio, ad esempio, diventa il comando

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

Non sono sicuro del motivo per cui vuoi leggere l'output di più righe, ma vorrei semplicemente utilizzare readla riga di prompt e echole righe precedenti.

Per rendere il codice più leggibile su più righe, non chiudere / aprire le virgolette tra le righe.

Prova questo:

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

Non voglio che stampi due righe! Voglio solo che il codice si adatti a 80 caratteri per riga nel codice sorgente dello script ! Grazie per la risposta però :)
Mateusz Piotrowski,

Non mi piace l'approccio che hai suggerito perché non c'è rientro. Se il mio readrientra in una funzione, il tuo approccio sembra incasinare la leggibilità.
Mateusz Piotrowski il

1

Trovo @ approccio di BinaryZebra utilizzando una variabile ad essere più pulito, ma si può anche farlo nel modo stavi tentando. Devi solo mantenere le interruzioni di riga tra virgolette:

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

Pensi che l'aggiunta di nuove righe dopo ogni riga aumenterebbe la leggibilità? Perché non stavo cercando il modo di inserirmi \nnel mio prompt. Volevo solo dividere il codice in più righe in modo che ogni riga fosse lunga al massimo 80 caratteri.
Mateusz Piotrowski,

1
@MateuszPiotrowski oh, ha molto più senso. Quindi la mia risposta non è molto utile. Modifica la tua domanda e chiarisci che desideri dividere il codice e non l'output. Sono su cellulare ora, ma vedrò se riesco a trovare qualcosa domani.
terdon

1
@MateuszPiotrowski fatto, ho aggiunto una versione funzionante di quello che stavi provando in origine.
terdon

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.