Como quebrar uma cadeia longa em várias linhas no prompt de read -p dentro do código-fonte?

7

Estou escrevendo um script de instalação que será executado como /bin/sh .

Existe uma linha solicitando um arquivo:

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

Eu gostaria de quebrar essa longa linha em muitas linhas, para que nenhuma delas ultrapasse 80 caracteres. Eu estou falando sobre as linhas dentro do código-fonte do script; não sobre as linhas que serão realmente impressas na tela quando o script for executado!

O que eu tentei:

  • abordagem Frist:

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

    Isso não funciona, pois não imprime Would you like to add this feature? [Y|n] .

  • Segunda abordagem:

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

    Não funciona tão bem. Imprime uma nova linha após o aviso. Adicionar a opção -n ao echo não ajuda: apenas 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
    
  • Minha solução atual é

    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 gostaria de saber se existe uma maneira melhor.

Lembre-se de que estou procurando uma solução /bin/sh compatível.

    
por Mateusz Piotrowski 26.03.2016 / 21:37

3 respostas

7

Antes de mais nada, vamos desacoplar a leitura da linha de texto usando uma variável:

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

Desta forma, o problema torna-se: Como atribuir duas linhas a uma variável.

Claro, uma primeira tentativa para fazer isso é:

a="line-1 \
line-2"

Escrito assim, o var a na verdade recebe o valor line-1 line-2 .

Mas você não gosta da falta de recuo que isso cria, bem, então podemos tentar ler as linhas no var a partir de um aqui-doc (esteja ciente de que as linhas recuadas dentro do aqui-doc precisam de uma aba, não espaços, para funcionar corretamente):

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

Mas isso falharia, já que, na verdade, duas linhas são gravadas em $a . Uma solução alternativa para obter apenas uma linha pode ser:

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

Isso é próximo, mas cria outros problemas adicionais.

Solução correta.

Todas as tentativas acima apenas tornarão esse problema mais complexo que precisa ser.

Uma abordagem muito básica e simples é:

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

O código para o seu exemplo específico é (para qualquer shell cujo read suporta -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 os outros shells, 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
    
por 27.03.2016 / 05:21
1

A barra invertida no final das linhas está permitindo a continuação do comando em várias linhas, não as quebras de linha reais na saída.

Portanto, sua primeira abordagem, por exemplo, torna-se o comando

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

Não sei por que você quer ler para gerar várias linhas, mas eu simplesmente usaria read para a linha de prompt e echo da (s) linha (s) anterior (es).

Para tornar o código mais legível em várias linhas, não feche / abra suas aspas entre as linhas.

Tente isto:

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

Eu acho a abordagem do BinaryZebra usando uma variável para ser mais limpa, mas você também pode fazer do jeito que você estavam tentando. Você só precisa manter as quebras de linha dentro das aspas:

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