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

18

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

Há 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

Gostaria de dividir esta longa linha em muitas linhas, para que nenhuma delas exceda 80 caracteres. Eu estou falando sobre as linhas dentro do código fonte do script; não sobre as linhas que realmente devem ser impressas na tela quando o script for executado!

O que eu tentei:

  • Primeira abordagem:

    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 é impresso 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 prompt. Adicionar -nopção ao echonã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 eu me pergunto se existe uma maneira melhor.

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

Mateusz Piotrowski
fonte
1
Sugiro que você 1. use um terminal mais amplo e / ou janela do editor (por exemplo, eu uso um terminal de 192 colunas por 51 linhas no meu monitor 1440p - ótimo para personalizar arquivos de log e editar o código-fonte no vim) e 2. aprender a aceitar o fato de que, às vezes, as linhas de código-fonte terão mais de 80 caracteres - é inevitável. Se eu usasse uma fonte menor, poderia ter um terminal ainda mais amplo, mas minha configuração atual é um bom compromisso entre largura e legibilidade.
26616 mai

Respostas:

16

Primeiro, vamos desacoplar a leitura da linha de texto usando uma variável:

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

Dessa maneira, o problema se torna: Como atribuir duas linhas a uma variável.

Obviamente, uma primeira tentativa de fazer isso é:

a="line-1 \
line-2"

Escrito assim, o var arealmente recebe o valor line-1 line-2.

Mas você não gosta da falta de recuo que isso cria, então podemos tentar ler as linhas no var de um documento aqui (lembre-se de que as linhas recuadas dentro do documento aqui precisam de uma guia, não de espaços, para funcionar corretamente):

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

Mas isso falharia, na verdade, duas linhas são gravadas $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 está próximo, mas cria outros problemas adicionais.

Solução correta.

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

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 cujos readsuportes -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 todas as outras conchas, 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

fonte
@BinaryZebra eu sei. Eu apenas corrigi o "para qualquer shell", pois nem todos os shells leram e nem todos os que possuem -p.
terdon
@terdon Estamos ambos de acordo Essa é a razão do agradecimento :-). Obrigado novamente.
1

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

Portanto, sua primeira abordagem, por exemplo, se torna 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ê deseja ler para gerar várias linhas, mas eu simplesmente usaria readpara a linha de prompt e echoas linhas anteriores.

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

Tente o seguinte:

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
fonte
Não quero imprimir duas linhas! Eu só quero que o código caiba em 80 caracteres por linha no código-fonte do script ! Obrigado pela resposta embora :)
Mateusz Piotrowski
Não gosto da abordagem que você sugeriu porque não há recuo. Se my readé recuado em uma função, sua abordagem parece atrapalhar a legibilidade.
Mateusz Piotrowski 27/03
1

Acho a abordagem do @ BinaryZebra usando uma variável para ser mais limpa, mas você também pode fazê-lo da maneira que estava tentando. Você só precisa manter as quebras de linha entre aspas:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY
terdon
fonte
Você acha que a adição de novas linhas após cada linha aumentaria a legibilidade? Porque eu não estava procurando a maneira de inserir \nno meu prompt. Eu só queria dividir o código em várias linhas para que cada linha tenha no máximo 80 caracteres.
Mateusz Piotrowski 26/03
1
@MateuszPiotrowski oh, isso faz muito mais sentido. Então minha resposta não é muito útil. Edite sua pergunta e esclareça que deseja dividir o código e não a saída. Estou no celular agora, mas verei se posso inventar algo amanhã.
terdon
1
@MateuszPiotrowski, adicionei uma versão funcional do que você estava tentando originalmente.
terdon
0

Que tal exatamente isso:

#! / bin / bash
leia -p "Olá
mundo
isto é um
multi-linha
prompt: "PROMPT
eco $ PROMPT

Desmond
fonte
Como você recua?
Mateusz Piotrowski