web-dev-qa-db-fra.com

Comment diviser une longue chaîne en plusieurs lignes dans l'invite de lecture -p dans le code source?

J'écris un script d'installation qui s'exécutera en tant que /bin/sh.

Une ligne demande un fichier:

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

Je voudrais diviser cette longue ligne en plusieurs lignes afin qu'aucune d'entre elles ne dépasse 80 caractères. Je parle de les lignes dans le code source du script; pas sur les lignes qui doivent être réellement imprimées à l'écran lors de l'exécution du script!

Ce que j'ai essayé:

  • Première approche:

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

    Cela ne fonctionne pas car il n'imprime pas Would you like to add this feature? [Y|n].

  • Deuxième approche:

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

    Ça ne marche pas aussi bien. Il imprime une nouvelle ligne après l'invite. Ajouter -n l'option pour echo n'aide pas: elle affiche simplement:

    -n goat oat may try to change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
    
  • Ma solution de contournement actuelle est

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

et je me demande s'il y a une meilleure façon.

N'oubliez pas que je recherche un /bin/sh solution compatible.

21
Mateusz Piotrowski

Tout d'abord, découplons la lecture de la ligne de texte en utilisant une variable:

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

De cette façon, le problème devient: Comment affecter deux lignes à une variable.

Bien sûr, une première tentative pour ce faire est:

a="line-1 \
line-2"

Écrit comme ça, le var a obtient en fait la valeur line-1 line-2.

Mais vous n'aimez pas le manque d'indentation que cela crée, eh bien, alors nous pouvons essayer de lire les lignes dans le var à partir d'un document ici (sachez que les lignes en retrait à l'intérieur du document ici ont besoin d'un onglet, pas d'espaces, pour fonctionner correctement):

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

Mais cela échouerait car en réalité deux lignes sont écrites dans $a. Une solution de contournement pour obtenir une seule ligne peut être:

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

C'est proche, mais cela crée d'autres problèmes supplémentaires.

Solution correcte.

Toutes les tentatives ci-dessus ne feront que rendre ce problème plus complexe qu'il ne doit l'être.

Une approche très basique et simple est:

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

Le code de votre exemple spécifique est (pour tout shell dont read prend en charge -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

Pour tous les autres coques, utilisez:

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

Je trouve @ l'approche de BinaryZebra en utilisant une variable pour être plus propre, mais vous pouvez également le faire comme vous le tentiez. Il vous suffit de conserver les sauts de ligne à l'intérieur des guillemets:

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

La barre oblique inversée à la fin des lignes permet la poursuite de la commande sur plusieurs lignes, et non des sauts de ligne réels dans la sortie.

Ainsi, votre première approche, par exemple, devient la commande

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

Je ne sais pas pourquoi vous voulez lire pour afficher plusieurs lignes, mais j'utiliserais simplement read pour la ligne d'invite et echo la ou les lignes précédentes.

Pour rendre le code plus lisible sur plusieurs lignes, ne fermez pas/n'ouvrez pas vos guillemets entre les lignes.

Essaye ça:

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

Et juste ceci:

 #!/bin/bash 
 read -p "Bonjour 
 monde 
 ceci est une 
 multi-ligne 
 Invite: "Invite 
 Echo $ Invite
0
Desmond